Обновление глубоко вложенного состояния в Redux - PullRequest
0 голосов
/ 02 июня 2019

Я обновляю проект «доска объявлений», который я сделал (курс стека MERN Брэда Траверси), чтобы включить лайки комментариев. В качестве простого примера рассмотрим Facebook: вы создаете сообщение, которое может понравиться людям, и люди могут отвечать комментариями, которые также могут понравиться.

У меня есть элемент состояния "post", который содержит лайки постов (массив post.likes), комментарии (массив post.comments) и лайки комментариев (где все становится сложно: массив, вложенный в массив post.comments ).

Как мне обновить вложенные массивы в моем редукторе, чтобы моя страница правильно отображалась? Прямо сейчас он записывает действие и показывает новые лайки / антипатии, когда страница перезагружается вручную, но не перезагружает саму страницу.

Я пытался обновить состояние, но реальность такова, что я не совсем уверен, как перебрать и обновить что-то глубоко вложенное.

Вот мое реальное почтовое состояние, предоставлено 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
  }
}

Он передает идентификатор поста и идентификатор пользователя, а затем фильтрует на основе того, существуют ли они или нет. Я также добавлю создателей действий, просто для ясности.

// 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
    })
  }
}

Сейчас он обновляет все в базе данных, но не обновляет состояние немедленно и не запускает повторную визуализацию.

Буду признателен за любую помощь.

Спасибо!

1 Ответ

0 голосов
/ 02 июня 2019

Было бы лучше, если бы вы также разбили логику удаления / добавления в своем редукторе:

  • ADD_COMMENT_LIKES - добавит подобное в массив вложенных лайков
  • REMOVE_COMMENT_LIKES - отфильтрует выбранное подобное по его идентификатору
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
    }
}

Прочитайте, как объединить редукторы и сформируйте свое состояние в виде одной независимой ветви.Это поможет вам структурировать ваш редуктор в более удобной для эксплуатации структуре.

...