在 React 中使用 useState 和 useEffect 的无限循环
Infinity loop using useState with useEffect in React
我想在每一秒后增加状态[second] = [second + 1]。
const [second,setSecond] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSecond(second+1)
}, 1000);
return () => clearInterval(interval);
}, []);
但是好像出现了无限循环,[second]只增加了一次,从0到1,就停止了运行。
我更改了我的代码
setSecond(second+1)
至
setSecond((second) => {return second+1})
这个运行没有问题:
const [second,setSecond] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSecond((second) => {return second+1})
}, 1000);
return () => clearInterval(interval);
}, []);
说真的,我还是没看清楚。谁能向我解释为什么?提前致谢!
查看您的代码,我认为问题在于 second 的值被绑定为 0。
const [second,setSecond] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSecond(second+1)
}, 1000);
return () => clearInterval(interval);
}, []);
这里当你的组件挂载时,useEffect 被执行。那时您正在创建一个函数并将其传递给 setInterval。此函数将在创建时使用 second
的值(等于 0)。因此,每次运行 setInterval 时,它都会执行 setSecond(0+1)
,它始终等于 1.
你提到的正确方法是有效的,因为你给它一个函数,每次执行时都会将状态的当前值传递给它。
再见,你设置second
的两种方式不一样。
这样:
setSecond(second+1)
不考虑second
的先前值。它只是尝试通过读取 second
的当前值将秒加 1。考虑到 setSecond
是异步的,在下一个 setInterval
上不能保证 second
会被前一个 setSecond
更新。所以这样你可能会出现故障。
这样:
setSecond((second) => {return second+1})
是正确的。在这里,您正在考虑 second
的先前值(通过使用箭头函数)。所以在这种情况下,second
将被正确更新。
你可以做一个测试:拿一个按钮,然后在 onclick 函数上尝试写:
setSecond(second+1)
setSecond(second+1)
您会看到 second
将增加 1(而不是预期的 2)。
现在像这样修改你的代码:
setSecond((second) => {return second+1})
setSecond((second) => {return second+1})
你会看到 second
会增加 2!
发生这种情况是因为 Hooks 是异步的。
我想在每一秒后增加状态[second] = [second + 1]。
const [second,setSecond] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSecond(second+1)
}, 1000);
return () => clearInterval(interval);
}, []);
但是好像出现了无限循环,[second]只增加了一次,从0到1,就停止了运行。
我更改了我的代码
setSecond(second+1)
至
setSecond((second) => {return second+1})
这个运行没有问题:
const [second,setSecond] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSecond((second) => {return second+1})
}, 1000);
return () => clearInterval(interval);
}, []);
说真的,我还是没看清楚。谁能向我解释为什么?提前致谢!
查看您的代码,我认为问题在于 second 的值被绑定为 0。
const [second,setSecond] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSecond(second+1)
}, 1000);
return () => clearInterval(interval);
}, []);
这里当你的组件挂载时,useEffect 被执行。那时您正在创建一个函数并将其传递给 setInterval。此函数将在创建时使用 second
的值(等于 0)。因此,每次运行 setInterval 时,它都会执行 setSecond(0+1)
,它始终等于 1.
你提到的正确方法是有效的,因为你给它一个函数,每次执行时都会将状态的当前值传递给它。
再见,你设置second
的两种方式不一样。
这样:
setSecond(second+1)
不考虑second
的先前值。它只是尝试通过读取 second
的当前值将秒加 1。考虑到 setSecond
是异步的,在下一个 setInterval
上不能保证 second
会被前一个 setSecond
更新。所以这样你可能会出现故障。
这样:
setSecond((second) => {return second+1})
是正确的。在这里,您正在考虑 second
的先前值(通过使用箭头函数)。所以在这种情况下,second
将被正确更新。
你可以做一个测试:拿一个按钮,然后在 onclick 函数上尝试写:
setSecond(second+1)
setSecond(second+1)
您会看到 second
将增加 1(而不是预期的 2)。
现在像这样修改你的代码:
setSecond((second) => {return second+1})
setSecond((second) => {return second+1})
你会看到 second
会增加 2!
发生这种情况是因为 Hooks 是异步的。