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

如何在函数执行时比较React state变量,解决掷骰子去平局无限循环问题

问题根源

  • React 的 setState 是异步批量更新的,你在 slowRoll 函数里读取到的 topRoll、botRoll 始终是函数执行时闭包捕获的旧值,不会随着 setTopRoll/setBotRoll 调用更新,所以 while 循环的判断条件永远不会变,导致无限循环。
  • 原有循环中没有加延时逻辑,就算状态能实时更新,也会出现骰子动画来不及展示就跳转到最终结果的问题。

最优实现方案

完全可以通过 Promise 实现,核心优化逻辑是:每次生成随机值后先存在临时变量中,不依赖 state 做平局判断,同时每次投掷之间加固定延时保证动画能正常展示,优化后的代码如下:

const [topRoll, setTopRoll] = useState(7);
const [botRoll, setBotRoll] = useState(7);
// 可选:加滚动锁避免用户重复触发动画
const rollingRef = useRef(false);

// 单次投掷,返回本次生成的两个点数
const rollDiceSix = () => {
  const newTop = Math.floor(Math.random() * 6) + 1;
  const newBot = Math.floor(Math.random() * 6) + 1;
  setTopRoll(newTop);
  setBotRoll(newBot);
  return { newTop, newBot };
};

const slowRoll = async () => {
  if (rollingRef.current) return;
  rollingRef.current = true;
  
  // 循环投掷直到两个点数不相等
  while (true) {
    // 控制动画帧间隔
    await new Promise(resolve => setTimeout(resolve, 250));
    const { newTop, newBot } = rollDiceSix();
    // 直接用本次生成的临时值判断,不需要等待state更新
    if (newTop !== newBot) break;
  }
  
  rollingRef.current = false;
};

可选优化建议

如果想要动画效果更自然,可以额外加一个计数器,要求至少滚动3-5次之后再判断是否平局,避免刚投一次就结束的突兀感。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:45:03