2016-07-25 1 views
1

У меня есть следующий объект, из которого я хочу удалить один комментарий.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:"[email protected]", 
    id:"e93863eb-aa62-452d-bf38-5514d72aff39", 
    post:"test", 
    title:"test" 
    } 

Создатель действие попадает в апи функция удаления с CommentID:

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

Мой апи удаляет комментарий и я посылаю идентификатор комментария к моему 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 имеют один и тот же объект, у которого есть комментарий, удаленный, который я нахожу загадочным.

Также компонент не обновляется (когда я обновить комментарий исчез, как новый апи сделан вызов, чтобы вернуть обновленный пост.

Все остальное, кажется, работает нормально, проблема, как представляется, в редукторе .

Я прочитал другие сообщения об неизменяемости, которые были релевантными, и я по-прежнему не в состоянии решить проблему. Я также исследовал и нашел библиотеку immutability.js, но прежде чем я узнаю, как использовать это, я хотел найти решение (возможно, трудно, но я хочу понять, как это работает!).

+0

И поэтому предложенный подход к структурированию хранилища Redux заключается в том, чтобы сохранить ваше состояние более плоским и нормализованным :) FYI. В настоящее время я работаю над новым набором страниц для документов Redux, описывающих, как писать логику редуктора, и обработка нормализованных данных является частью этого. Описание задачи находится на странице https://github.com/reactjs/redux/issues/1784, и у нее есть ссылка на страницы WIP.Вам может быть интересно прочитать их. – markerikson

+0

Да, работа вокруг может быть на самом апи – alexi2

ответ

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

Edit:

Второй рабочий раствор

Я нашел второй гораздо более лаконична решение, комментарии приветствуются:

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

появляется Этот код чтобы непосредственно мутировать объект состояния. Вы создали новый массив, у которого удаленный элемент отфильтрован, но затем вы напрямую назначаете новый массив msgCommentsOne.data.comments. Поле data - это то же самое, что уже было в состоянии, поэтому вы его прямо изменили. Чтобы корректно обновлять данные неизменно, вам нужно создать новый массив comments, новый объект data, содержащий комментарии, новый объект msgComments, содержащий данные, и новый объект state, содержащий msgComments. Весь путь вверх по цепочке :)

Часто задаваемые вопросы по Redux дают немного больше информации по этой теме, по адресу http://redux.js.org/docs/FAQ.html#react-not-rerendering.

У меня есть ряд ссылок на статьи, в которых говорится об управлении равными Javascript данными неизменно, на https://github.com/markerikson/react-redux-links/blob/master/immutable-data.md. Кроме того, существует множество библиотек-утилит, которые могут помочь в абстрактном процессе выполнения этих вложенных обновлений неизменно, которые я перечислил в https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md.

+0

Что вы думаете о рабочем решении выше? – alexi2