React-Redux开发井字棋时dispatch checkResult存在状态更新延迟问题
问题原因
- 核心原因是你调用
checkResult(board)时传入的是更新前的旧棋盘数据:你在draw函数中拿到的board参数是组件props传入的、执行落子操作前的状态值。dispatch(drawXAction(squareIndex))确实会触发Redux store更新,但这个更新只会同步到组件的下一次props渲染,不会修改当前函数作用域内的board变量,所以胜利判定永远比实际落子慢一步。 - 额外可排查问题:你的
checkResult函数中判定O方胜利的判断条件写的是checkVictory(board, '0'),这里用的是数字0,如果你的O玩家标识是字母O的话,这部分逻辑也会失效。
解决方案
方案1:将胜利判定逻辑移入reducer(最符合Redux数据流规范)
每次reducer处理完DRAW_X/DRAW_O的action、生成最新的board状态后,直接调用checkResult方法用最新的board做判定,同步更新胜负状态。不需要在dispatch落子后手动调用判定,从根源避免拿旧数据的问题。
方案2:手动构造最新棋盘传入判定函数
落子后先基于旧board生成更新后的新board,再将新board传给checkResult,修改示例如下:
const mapDispatchToProps = dispatch => ({ draw: (board, players, squareIndex) => { if (!board[squareIndex]) { // 先构造更新后的新棋盘 const newBoard = [...board] if (players[players.turn] === 'X') { newBoard[squareIndex] = 'X' dispatch(drawXAction(squareIndex)); } else { newBoard[squareIndex] = 'O' dispatch(drawOAction(squareIndex)); } // 传入新棋盘做判定 dispatch(checkResult(newBoard)); dispatch(toggleTurnAction()); } } });
方案3:在组件生命周期中监听board变化触发判定
如果是函数组件可以用useEffect,类组件用componentDidUpdate,监听props中board的变化,每次board更新时自动执行胜利判定,确保拿到的永远是最新的棋盘数据。
内容的提问来源于stack exchange,提问作者Kate
相关产品推荐
相关产品推荐

