React调用setState存储setTimeout返回值后状态仍为undefined问题求解
React useState状态更新后立即读取为undefined问题解答
问题原因
- React 中的
useState状态更新是异步批量执行的,调用setIdleEvent时不会立即修改当前渲染上下文里的idleEvent变量,只会将更新任务加入队列。当前所有同步代码执行完成后,才会触发组件重渲染,新一轮渲染中useState返回的idleEvent才是更新后的值。 - 两次写法里的
console.log('idleEvent', idleEvent)都属于当前渲染周期的同步代码,读取的是本次渲染初始化时的旧值。因为你声明useState时没有传入初始值,所以默认值为undefined,这和你是否提前把定时器ID存入临时变量foo没有关系。
解决方法
根据你的使用场景可以选择以下三种方案:
- 设置后立即使用该值的场景:直接使用临时变量即可,不需要从状态中读取:
const foo = setTimeout(onIdle, idleTimeout); console.log('foo:', foo); setIdleEvent(foo); // 后续需要即时操作定时器直接使用foo即可,例如clearTimeout(foo)
- 需要在状态更新后执行对应逻辑的场景:用
useEffect监听idleEvent变化,回调会在状态更新、组件重渲染完成后触发:
const [idleEvent, setIdleEvent] = useState<NodeJS.Timeout>(); useEffect(() => { if (idleEvent) { console.log('更新后的idleEvent:', idleEvent); // 此处写入状态更新后需要执行的逻辑 } }, [idleEvent]);
- 需要随时同步读取最新值的场景:改用
useRef存储定时器ID,useRef的current属性修改是同步生效的,不会触发组件重渲染:
// 声明ref存储定时器ID const idleEventRef = useRef<NodeJS.Timeout>(); // 赋值操作同步生效 idleEventRef.current = setTimeout(onIdle, idleTimeout); // 可以随时读取到最新值 console.log('实时idleEvent:', idleEventRef.current);
内容的提问来源于stack exchange,提问作者Peter Kronenberg
相关产品推荐
相关产品推荐

