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

React-Redux update state of immutable object with nested array, delete element from array

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

    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" 
    }

动作创建者点击 api 删除功能,评论 ID:

// 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 工作并且评论被删除。问题是更新减速器中的状态。经过多次试验和错误,我正在尝试这个。

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};

声明和声明都 return 同一个对象,删除了我觉得令人费解的适当注释。

组件也没有更新(当我刷新时,注释消失了,因为对 return 进行了新的 api 调用,更新后的 post。

其他一切似乎都正常,问题似乎出在减速器上。

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

第一个可行的解决方案

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)
        ]
      }
    }
  };

该代码似乎直接改变了状态对象。您已经创建了一个新数组,其中过滤掉了已删除的项目,但您随后直接将新数组分配给 msgCommentsOne.data.commentsdata 字段与状态中已有的字段相同,因此您直接修改了它。要正确地不可变地更新数据,您需要创建一个新的 comments 数组、一个包含评论的新 data 对象、一个包含数据的新 msgComments 对象和一个新的 state 包含 msgComments 的对象。一直向上链:)

Redux 常见问题解答在 http://redux.js.org/docs/FAQ.html#react-not-rerendering.

提供了关于此主题的更多信息

我在 https://github.com/markerikson/react-redux-links/blob/master/immutable-data.md . Also, there's a variety of utility libraries that can help abstract the process of doing these nested updates immutably, which I have listed at https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md.

上有许多文章链接,这些文章讨论了不可变地管理普通 Javascript 数据