Проблема слияния объекта с состоянием в Angular NgRx

#angular #typescript #ecmascript-6 #ngrx

#angular #typescript #ecmascript-6 #ngrx

Вопрос:

Я прочитал это руководство по созданию хранилища NgRx, поэтому я создал простое хранилище со следующей формой.

 export const initialState: IState = {
  app: initialAppState
};

export function getInitialState(): IState {
  return initialState;
}

export interface IApp {
  id?: string;
  testMode?: boolean;
  authenticated?: boolean;
  user?: User;
  role?: string;
}

export interface IAppState {
  app: IApp;
}

export const initialAppState: IAppState = {
  app: {
    id: null,
    testMode: false,
    authenticated: false,
    user: null,
    role: 'END_USER'
  }
};
  

У него есть одно действие PatchApp с редуктором, которое выглядит следующим образом

 export const appReducers = (state = initialAppState, action: AppActions): IAppState => {
  switch (action.type) {
    case AppActionTypes.PatchApp: {
      return { ...state, app: action.payload };
    }

    default:
      return state;
  }
};
  

Теперь мне это кажется очень простым. У нас есть начальное состояние, которое хранится в app свойстве. Если мы получим полезную нагрузку для обновления authenticated свойства в существующем состоянии, я бы ожидал, что редуктор перезапишет только это свойство, а не все состояние.

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

Итак, если у меня есть начальное состояние, подобное этому:

 export const initialAppState: IAppState = {
  app: {
    id: null,
    testMode: false,
    authenticated: false,
    user: null,
    role: 'END_USER'
  }
};
  

тогда я делаю PatchApp с {authenticated: true, id: 'someid'} , я бы ожидал action.payload перезаписи / слияния / исправления существующего объекта.

Вместо этого происходит перезапись всего хранилища get ТОЛЬКО с помощью свойства. Итак, после выполнения вышеупомянутого приложения для исправления у нас будет только authenticated id набор реквизитов и .

Есть идеи, почему мой редуктор работает не так, как ожидалось? Я прочитал статью от Флавио Копеса и ничего не вижу, где я ошибаюсь.

Я также пытался использовать Object.assign() для объединения объектов.

 return Object.assign({}, state, { app: action.payload });
  

У меня есть CodeSandbox, который иллюстрирует проблему, которую я пытаюсь решить.

https://codesandbox.io/s/oxj7xx5n35?fontsize=14

Ответ №1:

Не уверен, правильно ли я понял, что вы пытаетесь сделать, но, похоже, вы хотите исправить только app часть состояния. Если это так, вы должны сделать это следующим образом:

 export const appReducers = (state = initialAppState, action: AppActions): IAppState => {
  switch (action.type) {
    case AppActionTypes.PatchApp: {
      return { 
        ...state, 
        app: {...state.app, ...action.payload} 
      };
    }

    default:
      return state;
  }
};
  

Комментарии:

1. Здесь важно также использовать оператор распространения для действия. {..state.app, action.payload} недопустимо