Open cheungseol opened 5 years ago
在hooks 中使用 setTimeout 方法,方法中访问到的函数 state 始终是初始值,而不是更新后的最新 state
在这个例子中,首先执行setCount 将 count 设为 5, 然后经过 3 秒后执行 setCountInTimeout, 将 countInTimeout 的值设置为count 的值
我们最初期望的是 这时候 countInTimeout 就等于 此刻 count 最新的值 5, 然而 countInTimeout 却保持了最开始的 count 值 0
import React, { useEffect, useState } from 'react'; const TimeoutExample = () => { const [count, setCount] = useState(0); const [countInTimeout, setCountInTimeout] = useState(0); useEffect(() => { setTimeout(() => { setCountInTimeout(count); // count is 0 here }, 3000); setCount(5); // Update count to be 5 after timeout is scheduled }, []); return ( <div> Count: {count} <br /> setTimeout Count: {countInTimeout} </div> ); }; export default TimeoutExample;
setTimeout 是一个闭包,setTimeout 函数执行的时候使用的参数 count 读取自setTimeout 函数创建的时候,即 0。 setTimeout 使用闭包的方式异步访问 count 的值。当整个函数组件re-render的时候,会创建出一个新的 setTimeout 函数一个新的闭包,但并没有改变最初封装它的那个闭包的值
作者也提到这么设计的初衷是满足这样的场景:比如订阅了一个ID,当随后需要取消订阅的时候,避免ID发生变化而造成不能取消订阅的问题
使用一个 container 来把最新的 state 也就是 count 的值穿进去,并在随后的 timeout 函数中读取最新的 state 。
可以使用 useRef。 通过 ref's current 来同步最新的 state, 然后在 timeout 函数中读取 current 的值。使用 ref 在异步callback函数中访问最新的 当前的 state
const countRef = useRef(count); countRef.current = count; const getCountTimeout = () => { setTimeout(() => { setTimeoutCount(countRef.current); }, 2000); };
参考: State from useState hook inside a setTimeout is not updated
useCallback deps 加上 count?
问题
在hooks 中使用 setTimeout 方法,方法中访问到的函数 state 始终是初始值,而不是更新后的最新 state
demo
在这个例子中,首先执行setCount 将 count 设为 5, 然后经过 3 秒后执行 setCountInTimeout, 将 countInTimeout 的值设置为count 的值
我们最初期望的是 这时候 countInTimeout 就等于 此刻 count 最新的值 5, 然而 countInTimeout 却保持了最开始的 count 值 0
原因
setTimeout 是一个闭包,setTimeout 函数执行的时候使用的参数 count 读取自setTimeout 函数创建的时候,即 0。 setTimeout 使用闭包的方式异步访问 count 的值。当整个函数组件re-render的时候,会创建出一个新的 setTimeout 函数一个新的闭包,但并没有改变最初封装它的那个闭包的值
作者也提到这么设计的初衷是满足这样的场景:比如订阅了一个ID,当随后需要取消订阅的时候,避免ID发生变化而造成不能取消订阅的问题
解决方法
使用一个 container 来把最新的 state 也就是 count 的值穿进去,并在随后的 timeout 函数中读取最新的 state 。
可以使用 useRef。 通过 ref's current 来同步最新的 state, 然后在 timeout 函数中读取 current 的值。使用 ref 在异步callback函数中访问最新的 当前的 state
参考: State from useState hook inside a setTimeout is not updated