#reactjs
#reactjs
Вопрос:
У меня есть компонент React. Внутри этого компонента я хочу, чтобы что-то росло и уменьшалось каждую секунду. Я пытаюсь использовать useState для этого.
Этот код не работает. Он просто повторно устанавливает значение false. Я не совсем понимаю, почему. Есть мысли?
const [fullWidth, setFullWidth] = useState(false);
let interval;
useEffect(() => {
startToggle();
return () => {
clearInterval(interval)
}
}, []);
const startToggle = () => {
interval = setInterval(() => {
setFullWidth(!fullWidth);
}, 1000)
}
Комментарии:
1. Вы уверены, что он устанавливает его в
false
, нетtrue
?
Ответ №1:
Даже если startToggle
объявлено снаружи useEffect
, оно все равно должно передаваться fullWidth
как зависимость внутри массива эффектов.
const { useEffect, useState } = React;
const App = () => {
const [fullWidth, setFullWidth] = useState(false);
useEffect(() => {
const interval = setInterval(() => {
setFullWidth((f) => !f);
}, 1000);
return () => {
clearInterval(interval);
};
}, []);
return fullWidth.toString();
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Комментарии:
1. В этом случае было бы лучше перейти
fullWidth
кstartToggle
явно, чтобы сделать это… более явно. В качестве альтернативы,setFullWidth(fullWidth => !fullWidth);
также может быть использовано.2. @FelixKling Это круто, так как тогда нам не нужно менять массив зависимостей. Однако, как насчет принципа подключения — reactjs.org/docs/… Это правило здесь не нарушено, Феликс?
3. @FelixKling ваше решение сработало. Почему это имеет значение?
4. @kinduser: я думаю, это так. Но также нет необходимости создавать новый интервал при каждом рендеринге, если мы уже можем получить «текущее» значение другим способом, IMO. Но каждый может выбрать, что ему подходит 🙂
5. @JSeabolt: в вашем решении интервал запускается только один раз при первом рендеринге и
startToggle
(с первого рендеринга) всегда будет ссылаться наfullWidth
из этого первого вызова рендеринга, когда он имел значениеfalse
. Передавая функцию обратного вызова, вы указываетеsetFullWidth
, чтобы она давала вам текущее значение этого состояния. Это обычная ловушка, в которую можно попасть.