[英]React: Updated state not reflecting in recursive useCallback
I am incrementing foo
in a useCallback hook called recursively .我在名为recursively的useCallback钩子中递增
foo
。 But, the incremented foo
won't reflect in the callback.但是,递增的
foo
不会反映在回调中。
const { useState, useCallback } = React; const App = () => { const [foo, setFoo] = useState(0); const recursiveCallback = useCallback(() => { // always logs 0 console.log(foo); // incrementing foo setFoo(foo + 1); setTimeout(() => { // recursive call recursiveCallback(); }, 250); }, [foo]); return <button onClick={recursiveCallback}>Click Me</button>; } ReactDOM.render(<App />,document.getElementById('root'));
<div id="root"></div> <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>
You are having a closure on foo===0
value, both in the log and in the setter function, to fix it you need to use functional update and useEffect
for logging:您在日志和设置器 function 中都关闭了
foo===0
值,要修复它,您需要使用功能更新和useEffect
进行日志记录:
const { useState, useCallback, useEffect } = React; const App = () => { const [foo, setFoo] = useState(0); const recursiveCallback = useCallback(() => { setFoo(prev => prev + 1); setTimeout(() => { recursiveCallback(); }, 250); }, [foo]); useEffect(() => { console.log(foo); }, [foo]); return <button onClick={recursiveCallback}>Click Me</button>; } ReactDOM.render( < App/>, document.getElementById('root'));
<div id="root"></div> <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>
useEffect()
with [foo]
dependency to see the changes after the state has been set.[foo]
依赖项的useEffect()
来查看更改。foo
should be a Functional update
foo
的 function 应该是Functional update
If the new state is computed using the previous state, you can pass a function to setState The function will receive the previous value , and return an updated value
If the new state is computed using the previous state, you can pass a function to setState The function will receive the previous value , and return an updated value
// incrementing foo
setFoo(previousFoo => previousFoo + 1);
Note: what happened if you did not choose functional update
?注意:如果您没有选择
functional update
会发生什么?
Well, if you chose setFoo(foo + 1);
好吧,如果你选择
setFoo(foo + 1);
, the next sate will be 2 only, after that, the state is not changed, useEffect
with dependency foo
is also not affected as well. ,下一个状态将仅为 2,之后,state 不会更改,带有依赖项
foo
的useEffect
也不受影响。
In short , if you need a previous state, you have to use functional update
.简而言之,如果您需要以前的 state,则必须使用
functional update
。
const { useState, useCallback, useEffect } = React; const App = () => { const [foo, setFoo] = useState(0); const recursiveCallback = useCallback(() => { // incrementing foo //setFoo(foo + 1); setFoo(previousFoo => previousFoo + 1); setTimeout(() => { // recursive call recursiveCallback(); }, 500); }, [foo]); useEffect(() => { console.log(foo); }, [foo]); return <button onClick={recursiveCallback}>Click Me</button>; } ReactDOM.render(<App />,document.getElementById('root'));
<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="root"></div>
Try changing this line尝试更改此行
setFoo(foo + 1);
to至
setFoo((foo) => foo + 1);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.