嵌套对象更新时 Redux 不会重新渲染

Max*_*s S 2 reactjs redux

这个问题请参考下面的函数:

const mapStateToProps = (state) => {
  return {
    currentPlaylist: state.currentPlaylist,
    currentSong: state.currentSong,
    localPlaylists: state.playlistsBySource['local'],
    videoSize: state.videoSize,
  };
}
Run Code Online (Sandbox Code Playgroud)

这是mapStateToProps容器的功能。我希望每次state.playlistsBySource['local']更新时都会重新渲染连接到此容器的组件。但是,即使state.playlistsBySource['local']更新它也不会呈现,因此我将代码更改为以下内容:

const mapStateToProps = (state) => {
  return {
    currentPlaylist: state.currentPlaylist,
    currentSong: state.currentSong,
    playlists: state.playlistsBySource,
    videoSize: state.videoSize,
  };
}
Run Code Online (Sandbox Code Playgroud)

然后每次更新时,连接的组件都会正确state.playlistsBySource['local']更新。但这是一种浪费,因为连接的组件不需要整个playlists.

为什么会发生这种情况,解决它的正确方法是什么?

更新

我像这样连接组件:

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(DumbComponent);
Run Code Online (Sandbox Code Playgroud)

在全局存储中更新后,DumbComponent不会调用的 render 方法state.playlistsBySource['local']

UPDATE2:Reducer 似乎是不可变的..我错过了什么吗?

case CONSTANTS.UPDATE_LOCAL_PLAYLIST:
  var playlistUpdated = transformedPlaylist(state[action.playlist.source], action);
  return updatedPlaylists(playlistUpdated, state);

function transformedPlaylist(state=[], action) {
  var oldPlaylist = _.find(state, (pl) =>
    pl.playlistName === action.playlist.playlistName);

  switch (action.type) {
    case CONSTANTS.RECEIVE_PLAYLIST:
    case CONSTANTS.UPDATE_LOCAL_PLAYLIST:
      return Object.assign({}, oldPlaylist, action.playlist, {
        isFetching: false,
      });
    default:
      return oldPlaylist
  }
}

function updatedPlaylists(playlistUpdated, oldPlaylists) {
  const source = playlistUpdated.source;
  const idxToUpdate = _.findIndex(oldPlaylists[source], (pl) =>
    pl.playlistName === playlistUpdated.playlistName
  );
  var playlists = Object.assign({}, oldPlaylists);
  playlists[source][idxToUpdate] = playlistUpdated;
  return playlists;
}
Run Code Online (Sandbox Code Playgroud)

mar*_*son 5

如果您可以为您的减速器发布相关代码,那将会有所帮助。但是,在绝大多数情况下,您的组件没有更新的原因是因为您直接改变了减速器中的状态,而不是一成不变地返回修改后的副本。有关更多信息,请参阅http://redux.js.org/docs/FAQ.html#react-not-rerendering 上的 Redux 常见问题解答。

更新

这一行看起来很可疑: playlists[source][idxToUpdate] = playlistUpdated;

请记住,如果您不可变地更新嵌套数据,则必须将复制和更新的项目一直返回到数据的顶部。

如果不查看上下文中的整个状态结构和操作,很难准确判断,但我认为您很可能确实在嵌套字段之一中进行了直接更改。

  • 这是一个浅拷贝。它复制上层对象的字段,但这些字段仍然指向相同的嵌套数据。因此,如果您直接写入嵌套对象,那么您就直接改变了它。 (2认同)