@Andreeyyy
Web программист

Почему reducer не видит изменения массива?

Добрый вечер! Вопрос по реакту и react-redux. У меня есть store с комментариями и я хочу добавить в него еще один комментарий. Он добавляется, но компонент, отображающий комментарии, не рендерится заново. Опытным путем я выяснил, что редюсер передает новый массив с комментариями ( data ) в store, но не вызывает повторный рендер компонента. Если в обьект к массиву комментариев добавить некий флаг и каждый раз менять его состояние, то все работает нормально. Но это все-таки костыль, как можно обойтись без него?

import * as Comments from '../constants/commentsConstants';

export function commentsReducer(state = {data: [], marker: false}, action) {
    switch (action.type) {
        case Comments.ADD_COMMENT: {
            let newData = state.data;
            newData.push({
                postId: action.payload.postId,
                body: action.payload.body,
                name: action.payload.name,
                id: state.data[state.data.length - 1].id + 1
            });
            
            state = {...state, is_fetching: false, data: newData, marker: !state.marker};
            // state = {...state, is_fetching: false, data: newData}; - Так не работает
            break;
        }
    }

    return state;
}
  • Вопрос задан
  • 51 просмотр
Решения вопроса 1
@i1yas
Документация по редьюсерам https://redux.js.org/basics/reducers
В частности:
It's very important that the reducer stays pure. Things you should never do inside a reducer:
Mutate its arguments;
Perform side effects like API calls and routing transitions;
Call non-pure functions, e.g. Date.now() or Math.random().


Вы мутируете приходящий state

Чинить надо как-то так:
export function commentsReducer(state = {data: [], marker: false}, action) {
    switch (action.type) {
        case Comments.ADD_COMMENT: {
            let newData = state.data.slice(); // копируем массив
            newData.push({
                postId: action.payload.postId,
                body: action.payload.body,
                name: action.payload.name,
                id: state.data[state.data.length - 1].id + 1
            });
            
            // никакого state = ...
            return {...state, is_fetching: false, data: newData};
        }
    }
    return state;
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы