React-Redux使用嵌套数组更新不可变对象的状态,从数组

时间:2016-07-25 03:07:19

标签: arrays reactjs redux immutability react-redux

我有以下对象,我想从中删除一条评论。

    msgComments = {
        comments: [
            { comment:"2",
              id:"0b363677-a291-4e5c-8269-b7d760394939",
              postId:"e93863eb-aa62-452d-bf38-5514d72aff39" },
            { comment:"1",
              id:"e88f009e-713d-4748-b8e8-69d79698f072",
              postId:"e93863eb-aa62-452d-bf38-5514d72aff39" }
        ],
    email:"test@email.com",
    id:"e93863eb-aa62-452d-bf38-5514d72aff39",
    post:"test",
    title:"test" 
    }

动作创建者使用commentId:

命中api删除功能
// DELETE COMMENT FROM POST

export function deleteComment(commentId) {
  return function(dispatch) {
    axios.post(`${API_URL}/datacommentdelete`, {
      commentId
    },{
      headers: { authorization: localStorage.getItem('token') }
    })
      .then(result => {
        dispatch({
          type: DELETE_COMMENT,
          payload: commentId
        });
      })
  }
}

我的api删除了评论,我将评论ID发送到我的Reducer,这个工作正常,api工作,评论被删除。问题是更新reducer中的状态。经过多次试验和错误,我正在尝试这个。

case DELETE_COMMENT:
  console.log('State In', state.msgComments);
  const msgCommentsOne = state.msgComments;
  const msgCommentsTwo = state.msgComments;
  const deleteIndexComment = state.msgComments.data.comments
    .findIndex(elem => elem.id === action.payload );
  const newComments = [
    ...msgCommentsTwo.data.comments.slice(0, deleteIndexComment),
    ...msgCommentsTwo.data.comments.slice(deleteIndexComment + 1)
  ];
  msgCommentsOne.data.comments = newComments;
  console.log('State Out', msgCommentsOne);
  return {...state, msgComments: msgCommentsOne};

AND状态下的两个状态都返回相同的对象,删除了相应的注释,我觉得这很令人费解。

该组件也没有更新(当我刷新评论时,因为新的api调用将返回更新的帖子。

其他一切似乎都运行正常,问题似乎出现在减速机上。

我已阅读其他有关不变性的帖子,我仍然无法找到解决方案。我还研究并发现了immutability.js库,但在我学习如何使用之前,我想找到一个解决方案(也许很难,但我想了解它是如何工作的!)。

2 个答案:

答案 0 :(得分:1)

第一个工作解决方案

case DELETE_COMMENT:
  const deleteIndexComment = state.msgComments.data.comments
    .findIndex(elem => elem.id === action.payload);

  return {
    ...state, msgComments: {
      data: {
        email: state.msgComments.data.email,
        post: state.msgComments.data.post,
        title: state.msgComments.data.title,
        id: state.msgComments.data.id,
        comments: [
          ...state.msgComments.data.comments.slice(0, deleteIndexComment),
          ...state.msgComments.data.comments.slice(deleteIndexComment + 1)
        ]
      }
    }
  };

编辑:

第二个工作解决方案

我找到了第二个更简洁的解决方案,欢迎评论:

case DELETE_COMMENT:
  const deleteIndexComment = state.msgComments.data.comments
    .findIndex(elem => elem.id === action.payload);

  return {
    ...state, msgComments: {
      data: {
        ...state.msgComments.data,
        comments: [
          ...state.msgComments.data.comments.slice(0, deleteIndexComment),
          ...state.msgComments.data.comments.slice(deleteIndexComment + 1)
        ]
      }
    }
  };

答案 1 :(得分:1)

该代码似乎直接改变了状态对象。您已经创建了一个新数组,其中已删除已删除的项目,但您可以直接将新数组分配给msgCommentsOne.data.commentsdata字段与状态中的字段相同,因此您直接修改了该字段。要以不可变的方式正确更新数据,您需要创建一个新的comments数组,一个包含注释的新data对象,一个包含数据的新msgComments对象和一个新的{{1}包含msgComments的对象。一直到链条:)

Redux常见问题解答确实提供了有关此主题的更多信息,位于http://redux.js.org/docs/FAQ.html#react-not-rerendering

我有很多文章链接到https://github.com/markerikson/react-redux-links/blob/master/immutable-data.md上关于管理普通Javascript数据的文章。此外,还有各种实用程序库可以帮助抽象出不可变地执行这些嵌套更新的过程,我在https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md列出了这些过程。