我有以下反应成分。
function App() {
const [counter, setCounter] = useState(0);
useEffect(() => {
setInterval(() => {
setCounter(counter+1)
}, 3000)
}, [counter]);
console.log(counter)
return (
<div>
hi
</div>
);
}
export default App;
我得到类似
的结果0
1
1
2
1
2
3 ...
我确实知道,每次调用setCounter都会重新渲染组件,并且每次渲染都会重新创建useEffect回调。我的问题是,不应因此而读取当时每个渲染器的计数值
1、2、3、4、5 ....
答案 0 :(得分:2)
但是仍然不应该同时读取每个渲染的计数值。所以结果应该是
是的,但是您正在建立一个setInterval
调用,该调用捕获计数器的值并每3秒重复一次setCounter(counter + 1)
。因此,每3秒,计数器将重置为设置间隔加1时捕获的值。每次这样做,效果挂钩都会再次触发,并每3秒重复设置一个新的回调。
您是要使用setTimeout
吗?
useEffect(() => {
setTimeout(() => {
setCounter(counter+1)
}, 3000)
}, [counter]);
// Output: 1, 2, 3, 4, 5 ....
答案 1 :(得分:0)
要了解发生了什么,我在代码中添加了console.log
个。如已接受的答案所解释
setInterval调用,捕获该计数器的值,并每3秒重复一次setCounter(counter + 1)。
为解决此问题,我在deps列表中添加了一个空数组以仅注册一次setInterval,并将回调传递给setCounter以捕获当前状态值
function App() {
const [counter, setCounter] = useState(0);
useEffect(() => {
setInterval(() => {
setCounter((storedCounter) => storedCounter+1 )
console.log(counter, 'captured value')
}, 3000)
}, []);
console.log(counter, ' state')
return (
<div>
hi
</div>
);
}
export default App;