如何在函数执行时比较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
相关产品推荐
相关产品推荐

