Есть список из 5 элементов. По умолчанию список (массив) должен отображать ["A", "B", "C", "D", "E"]. Каждую секунду элементы должны поворачиваться на одну позицию:
Список через 1 секунду: ["B", "C", "D", "E", "A"];
Через 2 секунды: ["C", "D", "E", "A", "B"];
Через 3 секунды: ["D", "E", "A", "B", "C"];
Я учусь, и мне нужна помощь. Как бы вы решили эту проблему? Это мое неправильное решение:
import React, { useState, useEffect } from "react";
import "./App.css";
function App() {
const [term, setTerm] = useState();
const [letter, setLetter] = useState([]);
let array = ["A", "B", "C", "D", "E"];
useEffect(() => {
const interval = () =>
setInterval(() => {
array.push(array.shift());
setLetter(array);
}, 1000);
interval();
return clearInterval(interval);
}, [array]);
return (
<div className = "center">
<input
type = "text"
value = {term}
onChange = {(e) => setTerm(e.target.value)}
/>
{letter &&
letter.map((l, i) => {
return (
<ul key = {l}>
<li>{l[0]}</li>
<li>{l[1]}</li>
<li>{l[1]}</li>
<li>{l[3]}</li>
<li>{l[4]}</li>
</ul>
);
})}
</div>
);
}
export default App;
Я только учусь, я застрял, и мне нужна помощь. Он меняется быстро, например, каждые 50 мс.
Я проанализирую ответ и извлеку из него уроки, потому что я не могу сделать это сам.
Здесь происходит то, что у вас есть useEffect
, прикрепленный к изменениям array
, который изменяется несколько раз внутри интервального обратного вызова.
useEffect
useEffect
Это смешивается и начинает быстро менять массив.
Я бы предложил работать с копией массива или чем-то в этом роде.
setInterval(() =>
let copy = […array];
copy.push(copy.shift());
setLetter(copy);
array = copy
}, 1000);
Еще одно предложение. Я бы также попытался не использовать дополнительную переменную array
, так как эти данные уже хранятся в letter
.
Вот как бы я это сделал.
const [letter, setLetter] = useState(["A", "B", "C", "D", "E"]);
useEffect(() => {
setTimeout(() =>
let copy = […letter];
copy.push(copy.shift());
setLetter(copy);
}, 1000);
}, [letter]);
Я не проверял это, поэтому я надеюсь, что это поможет.
Я этого не понимаю. Начинается нормально, потом начинает ускоряться, а потом снова быстро. Не могли бы вы мне помочь?
Привет. Я отредактировал пример, и теперь он должен работать. Вместо setInterval
я просто использовал setTimeout
, который срабатывает только один раз, через заданное время, и нам не нужно его очищать.
ДА, мой мужчина. Спасибо так чертовски больше. Теперь он работает безупречно. Приятного аппетита. Спасибо еще раз.
Я бы посоветовал вам избегать изменения вашего массива. Вместо использования push
и shift
создайте новую версию массива с помощью arr => [...arr .slice (1), arr [0]]
или с помощью concat
:
const {useState, useEffect} = React;
const App = () => {
const [letters, setLetters] = useState (["A", "B", "C", "D", "E"])
useEffect(() => {
const timer = setTimeout (
() => setLetters (arr => arr .slice (1) .concat (arr [0])),
1000
)
return () => clearTimeout (timer)
})
return (<div>{letters .join (' ')}</div>)
}
ReactDOM .render (<App/>, document .getElementById ("main"))
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id = "main"></div>
Изменение данных только через сеттер делает вещи более последовательными.
Обратите внимание, что это будет работать без возврата clearTimeout
, но, вероятно, это хорошая привычка.
Вау, какое отличное решение. Ваш ответ лучший. Спасибо. Можете ли вы помочь мне с чем-то еще? Когда я пытаюсь получить доступ к Apple Music API (я использую Axios и устанавливаю параметры), к URL-адресу добавляются дополнительные символы, поэтому я получаю ответ 404. URL-адрес должен выглядеть так : https://itunes.apple.com/search?term=eminem
, но он превращается в https://itunes.apple.com/search?term=&0=eminem
. Дополнение =&0
. Почему это происходит? Я задам отдельный вопрос, если вы захотите, и поделюсь ссылкой здесь, то есть, если вы готовы мне помочь.
Просто задайте еще один вопрос после того, как вы провели собственное исследование. Если вдруг увижу и заинтересуюсь, могу попробовать помочь. Не стесняйтесь добавлять ссылку на этот вопрос в комментариях здесь, но никаких гарантий.
clearInterval
принимает идентификатор интервала (возвращается при вызовеsetInterval
), а не функцию.