Search code examples
angularrxjsngrxngrx-effectsngrx-entity

How to create or delete multiple data together with ngrx?


In conjunction with all the "flux architecture" (actions, effects, reducers etc ...) and rxjs I am trying to create and or delete multiple data.

And I have the following problems:

  1. How to create or delete multiple data both in the backend and in entities in the state?
  2. I've been researching and people said to use forkJoin, but how is it used with flux architecture?
  3. How to receive this data in real time and make other requests wait for them to arrive?

Here's an example of what I'm doing:

BACKEND SERVICE:

create(peoples: Array<IPeople>): Observable<Array<IPeople>> {
        const https = [];
        peoples.forEach((people) => https.push(this.httpClient.post<IPeople>(this.endpoint, people)));
        return forkJoin([]);
    }

EFFECTS

createAll$ = createEffect(() =>
    this.action$.pipe(
        ofType(fromPeopleActions.CREATE),
        mergeMap((action) => {
            return this.backend.create(action.people).pipe(
                map((people) => fromPeopleActions.CREATE_SUCCESS({ people })),
                catchError((error) => of(fromPeopleActions.CREATE_FAIL({ error: this.requestHandler.getError(error) })))
            );
        })
    )
);

REDUCER:

const peopleReducer = createReducer(
    INIT_STATE,
    on(fromPeopleAction.GET_ALL_SUCCESS, fromPeopleAction.CREATE_SUCCESS, fromPeopleAction.DELETE_SUCCESS, (state, { peoples }) => adapter.addMany(peoples, { ...state, loading: false })),
    on(fromPeopleAction.GET_ALL_FAIL, fromPeopleAction.CREATE_FAIL, fromPeopleAction.DELETE_FAIL, (state, { error }) => ({ ...state, error, loading: false }))
);

CALL

ngOnInit(): void {
    this.peopleDispatchService.getAll();
    this.peopleSelectorsService.loading.subscribe((isLoading) => {
        if (!isLoading) {
            this.peopleSelectorsService.total.subscribe((total) => {
                console.log(total);
                if (total === 0) {
                    this.peopleDispatchService.create([
                        { id: '0', isMain: true, name: 'THIAGO DE BONIS CARVALHO SAAD SAUD', avatar: 'assets/users/thiagobonis.jpg', messages: null },
                        { id: '1', isMain: false, name: 'BILL GATES', avatar: 'assets/users/billgates.jpg', messages: null },
                        { id: '2', isMain: false, name: 'STEVE JOBS', avatar: 'assets/users/stevejobs.jpg', messages: null },
                        { id: '3', isMain: false, name: 'LINUS TORVALDS', avatar: 'assets/users/linustorvalds.jpg', messages: null },
                        { id: '4', isMain: false, name: 'EDSGER DIJKSTRA', avatar: 'assets/users/dijkstra.jpg', messages: null },
                    ])
                } else {
                    this.peopleSelectorsService.allIds.subscribe((ids) => this.peopleDispatchService.delete(ids.toString()));
                }
            });
        }
    });
}

Solution

  • You do it almost right

    create(people: Array<IPeople>): Observable<Array<IPeople>> {
      return forkJoin(
        ...people.map(person => this.httpClient.post<IPeople>(this.endpoint, person)),
      );
    }
    

    Also fromPeopleAction.DELETE_SUCCESS and addMany sound strange together. I would add an independent on for it.

    now create will cause the creation requests.

    How to create or delete multiple data both in the backend and in entities in the state?

    • the way you do is fine.

    I've been researching and people said to use forkJoin, but how is it used with flux architecture?

    • check my example above

    How to receive this data in real time and make other requests wait for them to arrive?

    • better would be to have a single request to fetch all data and then transform the response to a lot of actions like ADD_MANY etc. Or to use forkJoin if your backend doesn't provide single endpoints for bulk data exchange.