Redux Deep Clone - состояние всегда равно - PullRequest
2 голосов
/ 12 октября 2019

У меня есть следующий редуктор в React Redux:

export const reducer = (state = initialStateData, action) => {
    switch (action.type) {
      case Action.TOGGLE_ARR_FILTER:
        {
          const subArr = state.jobOffers.filters[action.key];
          const filterIdx = subArr.indexOf(action.value[0]);
          const newArr = { ...state.jobOffers.filters
          };

          if (filterIdx !== -1) {
            newArr[action.key].splice(filterIdx, 1);
          } else {
            newArr[action.key].push(action.value[0]);
          }

          return {
            ...state,
            jobOffers: {
              ...state.jobOffers,
              filters: {
                ...newArr,
              },
            },
          };
        }

А это мой объект:

const initialStateData = {
  jobOffers: {
    filters: {
      employments: [],
      careerLevels: [],
      jobTypeProfiles: [],
      cities: [],
      countries: [],
    },
    configs: {
      searchTerm: '',
      currentPage: 1,
      pageSize: 5,
    },
  },
};

Кажется, что редуктор как таковой работает, он корректно переключает значения.

Но: Redux всегда показывает "состояния равны", что плохоизменения не распознаются.

Может кто-нибудь помочь? Я предполагаю, что возвращаю новый объект ..

Ответы [ 2 ]

1 голос
/ 12 октября 2019

вы можете использовать Immer , Redux также использует это для неизменяемых обновлений для вложенных материалов. Из-за этого вы можете писать редукторы, которые выглядят как «видоизмененные», но обновления фактически применяются неизменно.

const initialStateData = {
  jobOffers: {
    filters: {
      employments: [],
      careerLevels: [],
      jobTypeProfiles: [],
      cities: [],
      countries: [],
    },
    configs: {
      searchTerm: '',
      currentPage: 1,
      pageSize: 5,
    },
  },
};
export const reducer = immer.produce((state = initialStateData, action) => {
    switch (action.type) {
      case Action.TOGGLE_ARR_FILTER:

            const subArr = state.jobOffers.filters[action.key];
            const filterIdx = subArr.indexOf(action.value[0]);
            const newArr = state.jobOffers.filters;

            if (filterIdx !== -1) 
              newArr[action.key].splice(filterIdx, 1);
            else 
              newArr[action.key].push(action.value[0]);

            return state;
           }
          })        

0 голосов
/ 12 октября 2019

Несмотря на то, что вы берете копию state.jobOffers.filters, она по-прежнему содержит ссылки на оригинальные дочерние массивы, такие как employments. Поэтому, когда вы изменяете newArr[action.key] с помощью splice или push, Redux не увидит этого изменения, поскольку это все та же ссылка на массив.

Вы можете заменить это:

if (filterIdx !== -1) {
  newArr[action.key].splice(filterIdx, 1);
} else {
  newArr[action.key].push(action.value[0]);
}

с:

newArr[action.key] = filterIdx !== -1 
    ? [...newArr[action.key].slice(0, filterIdx), ...newArr[action.key].slice(filterIdx+1)]
    : [...newArr[action.key], action.value[0]]);

Кстати, вам не нужно копировать newArr снова , поскольку это уже копия filters. Вы можете заменить:

filters: {
    ...newArr,
},

просто:

filters: newArr,
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...