You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useCallback内setState后如何获取最新状态值

React中setState后在定时器中获取最新state值的解决方案

你遇到的问题是闭包捕获旧值导致的:useCallback会捕获当前渲染周期的player1和player2,而setTimeout的回调会保留这个闭包环境,1秒后执行时拿到的还是更新前的旧值。同时React的setState是异步更新,不能在调用set之后直接拿到新的state值。

下面是两种直接有效的解决方法:

方法一:直接使用局部变量存储新值

既然你已经明确要设置的新值(player1的新值是传入的value,player2的新值是随机生成的结果),可以把这些新值存在局部变量里,直接传给winConditionCheck,完全避开state的闭包问题:

const playerInputHandler = React.useCallback((value) => {
    // 把新值存在局部变量里
    const newPlayer1 = value;
    const newPlayer2 = Math.floor(Math.random() * 3) + 1;
    
    setPlayer1(newPlayer1);
    setPlayer2(newPlayer2);

    setTimeout(() => {
        // 直接用局部变量里的最新值
        winConditionCheck(newPlayer1, newPlayer2);
    }, 1000);
}, [winConditionCheck]); // 依赖项只保留winConditionCheck即可

这个方法最简单,也最适配你当前的场景,因为新值是可以提前明确获取到的。

方法二:用useRef同步最新state值

如果后续场景更复杂(比如需要基于旧state计算新值,无法提前拿到明确的新值),可以用useRef来实时同步state的最新状态,这样在任何地方都能获取到最新值:

首先定义ref并同步state:

const player1Ref = React.useRef(player1);
const player2Ref = React.useRef(player2);

// 每次state更新时,同步ref的current值
React.useEffect(() => {
    player1Ref.current = player1;
    player2Ref.current = player2;
}, [player1, player2]);

然后修改你的事件处理函数:

const playerInputHandler = React.useCallback((value) => {
    setPlayer1(value);
    setPlayer2(Math.floor(Math.random() * 3) + 1);

    setTimeout(() => {
        // 从ref中获取最新的state值
        winConditionCheck(player1Ref.current, player2Ref.current);
    }, 1000);
}, [winConditionCheck]);

useRef的current属性是可变的,不会受React渲染周期的闭包限制,所以能始终拿到最新的state值。

内容的提问来源于stack exchange,提问作者Fuad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 11:03:25