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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:45:02