React Redux如何在渲染前通过dispatch更新状态?贪吃蛇开发故障求助
问题根源
Redux的dispatch更新状态后,组件需要完成重新渲染才能通过useSelector拿到最新的状态值。在当前按键事件的执行上下文里,你从useSelector取到的init始终是本次渲染时的旧值,所以紧接在dispatch之后调用moveSnake时,读取到的direction还是更新前的旧值,就会出现方向不生效的问题。
解决方案
方案1:直接传递方向参数(适合按一次按键移动一次的玩法)
按键时已经明确要切换的目标方向,可以直接将方向作为参数传给moveSnake,不需要等待状态更新:
const onKeyDown = (e) => { console.log("_______________") e = e || window.event; let targetDirection; switch (e.keyCode) { case 38: targetDirection = 'UP' break; case 40: targetDirection = 'DOWN' break; case 37: targetDirection = 'LEFT' break; case 39: targetDirection = 'RIGHT' break; default: return; } dispatch({type: targetDirection}) // 直接传入最新方向,不用从旧状态里读取 moveSnake(targetDirection) } const moveSnake = (direction) => { let dots = [...init.snakeDots]; let head = dots[dots.length - 1]; // 优先使用传入的方向参数 switch (direction) { case 'RIGHT': console.log("into move", direction) head = [head[0] + 2, head[1]]; break; case 'LEFT': console.log("into move", direction) head = [head[0] - 2, head[1]]; break; case 'DOWN': console.log("into move", direction) head = [head[0], head[1] + 2]; break; case 'UP': console.log("into move", direction) head = [head[0], head[1] - 2]; break; default: break; } dots.push(head); dots.shift(); dispatch({ type:"MOVE_SNAKE", dots }) }
方案2:状态驱动移动逻辑(适合自动定时移动的常规贪吃蛇玩法)
把移动逻辑放到监听状态变化的useEffect中,只有Redux状态更新完成后才会触发移动,此时拿到的一定是最新的方向值:
useEffect(() => { checkIfOutOfBorders() // 状态更新完成后再执行移动,此时init是最新值 moveSnake() }, [init]) const onKeyDown = (e) => { console.log("_______________") e = e || window.event; // 按键只需要更新方向状态即可 switch (e.keyCode) { case 38: dispatch({type: "UP"}); break; case 40: dispatch({type: "DOWN"}); break; case 37: dispatch({type: "LEFT"}); break; case 39: dispatch({type: "RIGHT"}); break; default: break; } }
内容的提问来源于stack exchange,提问作者Manveru
相关产品推荐
相关产品推荐

