Как обновить или удалить вложенный объект внутри сущностей ngrx?

Как обновить или удалить вложенный объект внутри сущностей ngrx, например, я хочу удалить первый элемент, который имеет 19 id из (charter.entities.scopes.data), как это показано в приведенном ниже хранимом объекте json внутри моего магазина ngrx

 charter: {
      ids: [
        1
      ],
      entities: {
        '1': {
          id: 1,
          projectName: 'Some Project',
          projectCode: '899',
          projectUniqueCode: '674a9596-50ee',
          projectStatus: 'construction',
          budgetCode: 'CC34',
          projectTypeOne: 'Goods',
          projectTypeTwo: 'New',
          donorName: 'Elza Hills',
          scopes: {
            data: [
              {
                id: 19,
                module: 'Miss Cassandra Cartwright I',
                description: 'In tempore quia asperiores aut ea cum optio minima nemo est et aspernatur est repudiandae voluptas ipsum.',
                time: '2018-01-23 15:37:36'
              },

              {
                id: 43,
                module: 'Leanne Douglas',
                description: 'Occaecati facere eligendi esse esse nostrum in et vitae assumenda molestias omnis quis sit qui aut omnis est.',
                time: '2018-01-23 15:37:36'
              },
            ]
          },
          assumptions: {
            data: [
              {
                id: 29,
                assumption: 'Doloremque quo nihil minima ad optio perspiciatis asperiores debitis mollitia at debitis porro quia nam accusantium illo consequatur labore cum.',
                comments: 'Inventore ut pariatur id laboriosam recusandae soluta quo sunt impedit aut velit.'
              },
              {
                id: 164,
                assumption: 'Dolores quam aut possimus sint fugiat natus quos quaerat saepe facilis harum molestiae.',
                comments: 'Cumque quis magni illo dolore quas nam officiis dolores enim soluta doloribus in sed eum ut sunt.'
              },
            ]
          },

Редуктор

export interface State extends EntityState<ProjectsCharter> {
  isLoading: boolean;
  isLoaded: boolean;
  selectedProjectsId: any;
}

export const adapter: EntityAdapter<ProjectsCharter> = createEntityAdapter({
  selectId: (state: ProjectsCharter) => state.id,
  sortComparer: false
});

export const initialState = adapter.getInitialState({
  isLoading: false,
  isLoaded: false,
  selectedProjectsId: null
});

export function reducer(state = initialState, action: CharterActions) {
  switch (action.type) {
    case CharterActionTypes.loadCharterSuccess:
      return {
        ...adapter.addOne(action.payload['data'], state),
        isLoading: false,
        isLoaded: true
      };
    case CharterActionTypes.updateScopeOnParent:
      const scopeEntity = { ...state.entities[action.payload.param] };
      scopeEntity.scopes.data = scopeEntity.scopes.data.map(item => {
        if (item.id === action.payload.id) {
          item.module = action.payload.module;
        }
        return item;
      });

      return {
        ...adapter.updateOne(scopeEntity, state)
      };
    default:
      return {
        ...state
      };
  }
}

Я могу обновить и изменить объект nestad с помощью этого редуктора, но проблема в том, что 1- он немного сложен, а также показывает меня в терминале во время компиляции error TS2339: Property 'map' does not exist on type 'Scope'. также Argument of type '{ id: string; projectName: string; projectStatus: string; projectCode: string; projectUniqueCode:...' is not assignable to parameter of type 'Update<ProjectsCharter>'.

2 ответа

Я настоятельно советую вам изменить свой магазин и нормализовать его. Посмотрите здесь: https://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html

При таком подходе у вас будут менее сложные редукторы, как описано здесь https://redux.js.org/docs/recipes/reducers/UpdatingNormalizedData.html

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

Согласно моей логике, следующие моды редуктора должны по крайней мере устранить ошибку TS2339.

Этот бит

Аргумент типа '{ id: string; имя_проекта: строка; projectStatus: строка; projectCode: string; projectUniqueCode:...'нельзя назначить параметру типа'Update'

просто говорит вам (бесполезно), что adapter.updateOne требует первого параметра шаблона { id, changes } но вы просто даете это changes,


export function reducer(state = initialState, action: CharterActions) {
  switch (action.type) {

    case CharterActionTypes.loadCharterSuccess:
      ...

    case CharterActionTypes.updateScopeOnParent:

      const id = action.payload.param;
      const entities = {...state.entities};
      const original = entities[id];

      const newScopes = original.scopes.data.map(item => {
        if (item.id === action.payload.id) {
          item.module = action.payload.module;
        }
        return item;
      });
      const changes = { scopes: { data: newScopes }} // Partial<ProjectsCharter>

      return {
        ...adapter.updateOne({ id, changes }, state)
      };
    }

    default:
      ...
  }
}

Позвольте мне предварить это, сказав, что идеальное решение - нормализовать ваши сущности с помощью чего-то вроде normalizr. Тем не менее, вот решение, которое мне подходит:

  1. Сделайте глубокий клон объекта состояния
  2. Используйте Javascript delete метод клонированного объекта
  3. Передайте этот новый объект как новое состояние

Итак, предположим, что ваше состояние выглядит примерно так:

{
  entities: {
   '1': {
     prop1: 'val1',
     nested: {
      '1': {
        prop1: 'val1'
      },
      '2': {
        prop2: 'val2'
      }
    }
  }
}

Если ваша цель - удалить entities[1].nested[1]просто используйте следующий код (обратите внимание, что я использую библиотеку lodash):

import * as _ from 'lodash'

on(Actions.sampleDeleteAction, (state) => {
  const clonedState = _.cloneDeep(state);

  delete clonedState.entities[1].nested[1];

  return { ...clonedState };
}

Очевидно, вы хотели бы добавить props к вашему действию, которые содержат необходимые значения индекса, которые вы используете для удаления, вместо того, чтобы явно использовать индексы, как в примере entities[1].nested[1].

Другие вопросы по тегам