在Redux中更新深层嵌套状态

时间:2019-06-02 12:39:46

标签: reactjs redux react-redux

我正在更新我所做的“留言板”项目(Brad Traversy的MERN堆栈课程)以包含喜欢的评论。举个简单的例子,想想Facebook:您创建一个人们喜欢的帖子,人们可以发表评论,也可以被喜欢。

我有一个“发布”状态,其中包含帖子赞(post.likes数组),评论(post.comments数组)和评论喜欢(事情比较棘手:嵌套在post.comments数组内部的数组) )。

如何在我的reducer中更新嵌套数组,以便我的页面正确重新渲染?现在,它会记录操作并在手动重新加载页面时显示新的点赞/不喜欢,但不会重新加载页面本身。

我尝试过更新状态,但是现实是,我不确定如何遍历和更新深层嵌套的内容。

这是我的实际职位状态,由Redux DevTools提供。

post: {
    posts: [],
    post: {
      _id: '5cebd8bcdc17fd5cd7e57a45',
      text: 'This is my brand new post.',
      name: 'Bobby Smith',
      avatar: '//www.gravatar.com/avatar/414868368393e3ba8ae5ff93eeb98de6?s=200&r=pg&d=mm',
      user: '5cd646c9a632b51373121995',
      likes: [
        {
          _id: '5cebd8d1dc17fd5cd7e57a47',
          user: '5cd36ce5fda120050ee64160'
        }
      ],
      comments: [
        {
          date: '2019-05-27T12:32:16.172Z',
          likes: [ /*-------- This ---------*/
            {
              _id: '5cebd8e1dc17fd5cd7e57a48',
              user: '5cd646c9a632b51373121995'
            }
          ],
          _id: '5cebd8d0dc17fd5cd7e57a46',
          text: 'And this is my brand new response.',
          name: 'John Doe',
          avatar: '//www.gravatar.com/avatar/b2b146dba9e0023cb56637f0df4aa005?s=200&r=pg&d=mm',
          user: '5cd36ce5fda120050ee64160'
        }
      ],
      date: '2019-05-27T12:31:56.598Z',
      __v: 3
    },
    loading: false,
    error: {}
  }
}

减速器:

const initialState = {
  posts: [],
  post: null,
  loading: true,
  error: {}
}

export default function(state = initialState, action) {
  const { type, payload } = action
  switch (type) {
    case UPDATE_COMMENT_LIKES:
      return {
        ...state,
        post: { ...state.post, comments: ???? }
      }
    default:
      return state
  }
}

先传递帖子ID和用户ID,然后根据它们是否已存在进行过滤。为了清楚起见,我还将添加动作创建者。

// Add like to comment
export const addCommentLike = id => async dispatch => {
  try {
    const res = await axios.put(`/api/posts/comment/like/${id}`)

    dispatch({
      type: UPDATE_COMMENT_LIKES,
      payload: { id, likes: res.data }
    })
  } catch (err) {
    dispatch({
      type: POST_ERROR,
      payload: { msg: err.response.statusText, status: err.response.status }
    })
  }
}

// Remove like from comment
export const removeCommentLike = id => async dispatch => {
  try {
    const res = await axios.put(`/api/posts/comment/unlike/${id}`)

    dispatch({
      type: UPDATE_COMMENT_LIKES,
      payload: { id, likes: res.data }
    })
  } catch (err) {
    dispatch({
      type: POST_ERROR,
      payload: { msg: err.response.statusText, status: err.response.status },
      loading: false
    })
  }
}

现在,它正在更新数据库中的所有内容,但不是立即更新状态并触发重新渲染。

我将尽一切帮助。

谢谢!

2 个答案:

答案 0 :(得分:1)

我知道为时已晚,但可能对某人有所帮助。我也曾经做过这门课;) 因此,在您的情况下,减速器将如下所示:

case UPDATE_COMMENT_LIKES:
  return {
    ...state,
    post: {
      ...state.post,
      comments: state.post.comments.map((comment) =>
        comment._id === payload.id
          ? { ...comment, likes: payload.likes }
          : comment
      )
    },
    loading: false
  };

答案 1 :(得分:0)

如果您还要在化简器中拆分删除/添加逻辑,那会更好:

  • ADD_COMMENT_LIKES-将喜欢添加到嵌套的喜欢数组
  • REMOVE_COMMENT_LIKES-将按其ID过滤所选内容
export default function(state = initialState, action) {

    const { type, payload } = action;

    switch (type) {
        case ADD_COMMENT_LIKES:
            return {
                ...state,
                post: {
                    ...state.post,
                    comments: [
                        ...state.post.comments,
                        likes: [
                            ...state.post.comments.likes,
                            payload <--- inserting the new like
                        ]
                    ]
                }
            }
        case REMOVE_COMMENT_LIKES:
            return {
                ...state,
                post: {
                    ...state.post,
                    comments: [
                        ...state.post.comments,
                        likes: [
                            ...state.post.comments.likes.filter((item) => item.id !== payload.id)
                        ]
                    ]
                }
        default:
            return state
    }
}

阅读如何combine reducers,并将您的状态形成为一个独立的分支。它将帮助您将减速器构造为更具可维护性的结构。