Redux DevTools Time Travel 无法正确更新 UI(仅在恢复操作时)

Redux DevTools Time Travel fails to update UI correctly (only when reverting actions)

我正处于 React+Redux 游戏的早期开发阶段,并遵循了 Redux 最佳实践:纯 reducer,presentational/container 组件分离,仅在 Reducer 中使用 getState()(而不是在action creator) 等。该应用程序似乎按预期工作,但当我尝试使用时间旅行反转操作时,即使状态 属性 map[][] 和它计算的连接组件道具按预期更改,结果没有正确反映在 UI 上(特别是玩家在地图上的位置不符合状态指示)。当我检查状态变化时,我可以看到所有必要的变化都在不同状态之间正确发生。这是我的减速器:

const gridReducer = (state, action) => {

  if (typeof state === 'undefined'){
    let dungeon = new Dungeon();
    dungeon.generate();
    return {
      boardWidth: Math.floor(((70/100) * window.innerWidth) / 20),
      boardHeight: Math.floor(((70/100) * window.innerHeight) / 20),
      map: dungeon.map,
      position: dungeon.playerPosition
    }
  }
  switch (action.type) {
    case 'GRID_RESIZE': 
      return {...state, 
              boardWidth: action.newBoardWidth,
              boardHeight: action.newBoardHeight
      }
    //This is where I have the issue, map correctly changes both when interacting with the game and when reversing using time travel however the UI fails to update (only in reverse)!
    case 'MOVE':
      let dungeonObj = new Dungeon(state.map.slice(), {...state.position});
      if (dungeonObj.movePlayer(action.direction)) {
        return {...state,
                position: dungeonObj.playerPosition,
                map: dungeonObj.map
               }
      } else return state;
    default:
      return state;
  }
}

这里是完整代码,想看的话!该应用程序目前仅支持通过按箭头键在地牢中移动玩家,并且视图应该始终基于玩家的位置居中(玩家在使用时间旅行时无法后退) http://s.codepen.io/sabahang/debug/GjrPNQ

PS: Dungeon.generate 确实使用了 Math.Random 但我只在 initialState 中使用了这个函数,对于调度的动作我只是做了一个浅拷贝通过将当前状态发送到 Dungeon 构造函数并使用其其他方法(例如 movePlayer)生成的地图

找到罪魁祸首。这根本不是 Redux 的错,而是 React 工作方式的问题!如果您是 React 的新手并且还没有掉入这个陷阱,请等待! 它与这样一个事实有关,即 Redux 中实现纯 Reducer 所需的大多数复制深度嵌套对象的传统方法实际上是对对象进行浅表复制,并且属性的内存引用仍然指向原始对象状态。 React 根据旧状态和新状态的深度比较更新 UI,当一些引用相同时,它无法正确更新 UI。这里我有一个二维数组 map[][] 这是一个对象,虽然我使用 ES6 扩展运算符来避免修改原始状态,因为正在制作卷影副本,但原始 map[][] 的深层嵌套索引正在修改中。一种解决方案是使用“Array.map()”来创建一个全新的对象,但我最终使用了 immutablejs,它解决了我的时间旅行滑块问题。

如果您不想花费数周时间在复杂的应用程序中追查类似的错误,那么这是一个强烈推荐的参考:http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html

并且有大量不变性助手可以根据您的特定需求提供帮助: https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md#immutable-update-utilities

这个仅对 Redux 看起来也很有趣: https://github.com/indexiatech/redux-immutablejs

这个问题可能与以下问题重复: