简体   繁体   English

如何更新或删除 ngrx 实体内的嵌套对象?

[英]how to update or remove the nested object inside ngrx entities?

how to update or remove nested object inside ngrx entities for example I want to delete the first element which has the 19 id from (charter.entities.scopes.data) as it shown in the bellow stored json object inside my ngrx store如何更新或删除 ngrx 实体内的嵌套对象,例如我想从 (charter.entities.scopes.data) 中删除第一个具有 19 id 的元素,如我的 ngrx 存储中的波纹管存储的 json 对象所示

 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.'
              },
            ]
          },

The Reducer减速机

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
      };
  }
}

I can update and modify the nestad object with this reducer but the problem is 1- it's a little bit complex and also show me in terminal in compile time error TS2339: Property 'map' does not exist on type 'Scope'.我可以使用这个减速器更新和修改 nestad 对象,但问题是 1-它有点复杂,并且还在终端中显示编译时error TS2339: Property 'map' does not exist on type 'Scope'. also Argument of type '{ id: string; projectName: string; projectStatus: string; projectCode: string; projectUniqueCode:...' is not assignable to parameter of type 'Update<ProjectsCharter>'. Argument of type '{ id: string; projectName: string; projectStatus: string; projectCode: string; projectUniqueCode:...' is not assignable to parameter of type 'Update<ProjectsCharter>'. Argument of type '{ id: string; projectName: string; projectStatus: string; projectCode: string; projectUniqueCode:...' is not assignable to parameter of type 'Update<ProjectsCharter>'.

I strongly advice you to change your store and normalize it.我强烈建议您更改您的商店并将其标准化。 Take a look here: https://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html看看这里: https : //redux.js.org/docs/recipes/reducers/NormalizingStateShape.html

With this approach you will have less complex reducers, as explained here https://redux.js.org/docs/recipes/reducers/UpdatingNormalizedData.html使用这种方法,您将拥有不那么复杂的减速器,如此处所述https://redux.js.org/docs/recipes/reducers/UpdatingNormalizedData.html

With a store shaped this way, you will have to build a complex reducer.使用这种形状的商店,您将不得不构建一个复杂的减速器。

According to my logic, the following reducer mods should at least eliminate the TS2339 error.根据我的逻辑,以下 reducer mods 至少应该消除TS2339错误。

This bit这一点

Argument of type '{ id: string; '{ id: string; 类型的参数projectName: string;项目名称:字符串; projectStatus: string;项目状态:字符串; projectCode: string;项目代码:字符串; projectUniqueCode:...' is not assignable to parameter of type 'Update' projectUniqueCode:...' 不可分配给类型为 'Update' 的参数

is just telling you (in a non-helpful way) that adapter.updateOne is requiring a first parameter of pattern { id, changes } but you are just giving it changes .只是告诉您(以无用的方式) 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:
      ...
  }
}

Let me preface this by saying the ideal solution is to normalize your entities with something like normalizr .最后,我要说的理想解决方案是像正常化您的实体前言本normalizr That said, here is a solution that works for me:也就是说,这是一个对我有用的解决方案:

  1. Make a deep clone of the state object对状态对象进行深度克隆
  2. Use the Javascript delete method on the cloned object在克隆对象上使用 Javascript delete方法
  3. Pass this new object as the new state将此新对象作为新状态传递

So let's assume your state looks something like this:因此,让我们假设您的状态如下所示:

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

If your goal is to delete entities[1].nested[1] , just use the following code (note that I am using the lodash library ):如果您的目标是删除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 };
}

Obviously, you would want to add props to your action that contain the necessary index values you are using to delete rather than explicitly using indexes as in the example entities[1].nested[1] .显然,您希望向包含用于删除的必要索引值的操作添加props ,而不是像示例entities[1].nested[1]那样显式使用索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM