Home > Software engineering >  How to remove an item with Angular NGRX based on the ID of a string?
How to remove an item with Angular NGRX based on the ID of a string?

Time:09-28

I want to implement a "removeCustomerById(id:string)" function. I'm 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}));
}

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

The problem is that my backend has not changed, and if I refresh my application, all deleted items are back again. I already have 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)

Must it be done as an 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 doesn't work, because the customerID of mergeMap((customerID: string) is an [OBJECT] instead of a string with the id. I don't 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?

It gives you an action! You receive the full Action as opposed to just its payload.

  • Related