简体   繁体   English

NgRx状态添加/更新为数组并保持同步

[英]NgRx state add/update as array and keep in sync

How do you update state with ngrx if you need to add more than one object? 如果需要添加多个对象,如何使用ngrx更新状态?

For instance, in the example below, one user can be associated with more than one task. 例如,在下面的示例中,一个用户可以与多个任务相关联。

Currently, when all tasks are returned, the store is updated twice, and on each update the last task is replaced by a new one. 当前,当所有任务都返回时,存储将更新两次,并且在每次更新时,最后一个任务将被新任务替换。 This is expected behaviour, but how would you initialise an array and capture updates to state as an array of objects and ensure that it is kept in sync ? 这是预期的行为,但是您将如何初始化数组并捕获更新以将状态表示为对象数组并确保其保持同步

task.reducer.ts 任务减少器

import * as TaskActions from './task.actions';
import { Action, createReducer, on } from '@ngrx/store';
import { ITask } from '../../models/task';

export interface State {
  task: ITask | null;
  error: any;
}

const initialState: ITask = {
  basketTotal: 0,
  carePlanPrice: 0,
  category: null,
  completionDate: null
};

export const taskReducer = createReducer(
  initialState,
  on(TaskActions.getData, state => ({ ...state })),
  on(TaskActions.dataReceived, (state, payload) => ({ ...state, payload })),
  on(TaskActions.dataNotReceived, state => ({ ...state })),
  on(TaskActions.signOut, state => ({ ...state })),
  on(TaskActions.signOutSuccess, state => ({ ...state, ...initialState })),
);

export function reducer(state: ITask | undefined, action: Action) {
  return taskReducer(state, action);
}

task.effect.ts 任务效果

  @Effect()
  getData$ = this.actions$.pipe(
    ofType(TaskActions.getData),
    switchMap(() => {
      return this.afs.collection<ITask>('tasks', ref =>
        ref.where('createdBy', '==', localStorage.getItem('uid'))).stateChanges().pipe(
      );
    }),
    mergeMap(actions => actions),
    map(action => {
      if (action.payload) {
        return TaskActions.dataReceived({ payload: TaskService.parseData(action.payload.doc.data()) });
      } else {
        return TaskActions.dataNotReceived();
      }
    })
  );

task.actions.ts task.actions.ts

import { createAction, props } from '@ngrx/store';
import { ITask } from '../../models/task';

export const getData = createAction('[Task] Get Data');
export const dataReceived = createAction('[Task] Data Received', props<{ payload: Partial<ITask> }>());
export const dataNotReceived = createAction('[Task] Data Not Received');
export const signOut = createAction('[Task] Sign Out');
export const signOutSuccess = createAction('[Task] Sign Out Success');

Update: 更新:

I tried 我试过了

on(TaskActions.dataReceived, (state, payload) => 
  ({ 
      ...state, 
      tasks: [...state.tasks,  payload.payload ] 
  })),

and this is the result: 结果是:

在此处输入图片说明

I was expecting an array with both items in place: 我期待有一个包含两个项目的数组:

task: [
  { ... }, { ... }
]

The spread syntax can also be used for arrays to create a clone. 扩展语法也可以用于数组以创建克隆。

on(TaskActions.dataReceived, (state, payload) => 
  ({ 
      ...state, 
      tasks: payload.condition ? [...state.tasks,  payload.newTask ] : []
  })),

See the Spread syntax docs 请参阅Spread语法文档

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

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