Объект мутирует в Redux несмотря на синтаксис Object.assign и Spread - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть функция генератора в Redux Saga, которая получает идентификатор, получает состояние и отправляет действие с состоянием без ключа объекта с соответствующим идентификатором в нем. Объект в редукторе, который он должен был заменить, не мутировал, выглядит следующим образом:

{
    [CURRENT YEAR]: {
      [DAY OF YEAR]: {
        [ID THAT SHOULD BE DELETED]: {}
      },
    },
};

Когда эта функция запускалась с использованием закомментированного оператора удаления, она изменяла бы все состояние в избыточном и во всех регистраторах Redux (пред. и после изменения), и мои селекторы вернут предыдущую запомненную версию, потому что никаких изменений не обнаружено. Я решил это, создав новый объект с loda sh Omit, но есть ли более быстрое или <21kb решение для этого? </p>

function* removeExerciseAsync(action: any) {
  const { currentDate, currentYear }: DateState = yield select((state: AppState) => state.date);
  const years = yield select(selectYears);

  const dayOfYear = currentDate.dayOfYear();


  const newYearState: DaySummaryTypes = Object.assign({}, years[currentYear]);

  const exerciseId = action.payload;

  if (!newYearState[dayOfYear][exerciseId]) return;

  // delete newYearState[dayOfYear][exerciseId];

  const newState = omit(newYearState, `${dayOfYear}.${exerciseId}`);

  yield put(updateYearExercises({ [currentYear]: newState }));
}

1 Ответ

1 голос
/ 11 апреля 2020

Object.assign делает поверхностную копию объекта, означает, что объект на верхнем уровне отличается, но вложенные объекты все еще ссылаются на предыдущие объекты. Здесь вы вносите изменения во вложенный объект, который имеет ту же ссылку, что и объект, находящийся в вашем хранилище с избыточностью, следовательно, изменяя состояние избыточности. Вы также можете попробовать скопировать вложенный объект так:

function* removeExerciseAsync(action: any) {
  const { currentDate, currentYear }: DateState = yield select((state: AppState) => state.date);
  const years = yield select(selectYears);

  const dayOfYear = currentDate.dayOfYear();


  const newYearState: DaySummaryTypes = {
    ...years[currentYear],
    [dayOfYear]: {
      ...years[currentYear][dayOfYear]
    }
  };

  const exerciseId = action.payload;

  if (!newYearState[dayOfYear][exerciseId]) return;

  delete newYearState[dayOfYear][exerciseId];

  // const newState = omit(newYearState, `${dayOfYear}.${exerciseId}`);

  yield put(updateYearExercises({ [currentYear]: newState }));
}
...