Home > Mobile >  Best Practice to remove an item with Angular NGRX
Best Practice to remove an item with Angular NGRX

Time:09-28

I want to implement a "removeCustomerById(id:string)" function. Im new to NGRX and not sure about how to implement it. Here is my approach.

Actions

// Delete Customer ========================
export const deleteSingleCustomerAction = createAction(
 ActionTypes.DeleteCustomerAction,
 props<{ customerID: string }>()
);
export const deleteSingleCustomerActionSuccess = createAction(
  ActionTypes.DeleteCustomerSuccessAction,
);

Reducer

// Delete Customer ========================
on(deleteSingleCustomerAction, (state, {customerID}) => ({
 ...state,
 loading:   true,
 customers: state.customers.filter(element => element.id !== customerID)
})),

CustomerTable Compoenent: delete function

onDeleteClick(element: CustomerElement): void {
 this.store.dispatch(deleteSingleCustomerAction({customerID:element.id}));
}

Actually, I have a correct UI behavior here. Selected elements are removed by clicking the "Remove" button.

But the problem is, that my Backend not changed and if I refresh my application, all deleted items are back again. I have already a function in my service for sending delete requests.

CustomerService

removeCustomberById(id: string) {
 // REST API CALL delete item by id
}

The question is how and when to call removeCustomberById(id: string)

It must be done as a NGRX Effect? Because it is a Side-Effect? Or do I need to call removeCustomberById(id: string) before dispatching?

Like this prototype

 onDeleteClick(element: CustomerElement): void {
  //REST delete
  deletedCustomer =  this.customerService -> REST delete Request element
  //dispatch
  this.store.dispatch(deleteSingleCustomerAction({customerID: 
  deletedCustomer.id}));
}

In my approach I decided to implement an Effect

deleteCustomersActionEffect = createEffect(
 () => this.actions$.pipe(
  ofType(ActionTypes.DeleteCustomerAction),
  mergeMap((customerID: string) => //<-this is wrong
  this.customerService.removeCustomberById(customerID)
    .pipe(
      map((customers: CustomerDTO[]) => (
        {
          type:    ActionTypes.DeleteCustomerSuccessAction,
          payload: customers
        }
      )),
    )),
  tap(() => console.log(ActionTypes.DeleteCustomerAction   " - Action 
 Dispatched"))
 ),
);

But this not works, because the customerID of mergeMap((customerID: string) is [OBJECT] instead of string with the id. I dont really understand how to build such an effect. How I can get the correct string id inside of my effect?

CodePudding user response:

You're nearly there! You do indeed want a side effect here, and I would recommend that your reducer react to the DeleteCustomerSuccessAction (that way you make sure your API has deleted the customer before deleting it in the frontend) as opposed to the DeleteCustomerAction (which, in my opinion, should only have the Effect react to it).

The solution lies in that infamous mergeMap of yours. Have a think about what exactly you are receiving there. What are you piped onto here? What does the previous step in the pipe give you?

...

An action! You receive the full Action as opposed to just its payload.

Hope that puts you on the right track...

  • Related