How do you update state with ngrx if you need to add more than one object?
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
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.