0

In my react app I create a store and reducer using redux.

And I have one state name as "cart" which is an object array.

And I want to remove and an element which I pass the id as a payload in reducer case only.

How can I remove an element from this state which is id equal to payload ID?

This is cart state structure

enter image description here

const reducer = (state = initialState, action) => {
       case actionTypes.QUANTITY_COUNT:
            const newCart = {...state.cart};
            if (newCart[action.id].quantity === 1){
                 //here i want to remove element from cart/newCart of Id as action.id
              }
}
  • 1
    You need to use `cart.filter( (c) => c.id !== action.payload ),` this logic for delete – Alamin Feb 08 '21 at 03:50
  • @Sheikh this is not working in my case because the cart is an array of object and it throws error when I use this. Don't know why –  Feb 08 '21 at 03:51
  • 1
    It's a normal method for delete, if you have faced an error, then you need to show your code. – Alamin Feb 08 '21 at 03:54
  • @Sheikh yes sure, How can I show you my code? –  Feb 08 '21 at 03:55
  • Please edit your main post and explain more details about your error or problem – Alamin Feb 08 '21 at 03:56
  • 1
    It's not working because cart is not an array of objects, but an object of objects based on your console.log – buzatto Feb 08 '21 at 03:56
  • yes something like the same So what should I do now for removing it? –  Feb 08 '21 at 03:58
  • Please include a [Minimal, Complete, and Reproducible](https://stackoverflow.com/help/minimal-reproducible-example) code example of the relevant code in your issue. – Drew Reese Feb 08 '21 at 04:00
  • 1
    I would look into fixing on why that's not an array, since I believe that's what you were looking for first, right? – buzatto Feb 08 '21 at 04:02
  • @buzatto yes, but the focus is to remove element from this. –  Feb 08 '21 at 04:05
  • Seems the `id` is also the object key, `delete newCart[action.id]`. – Drew Reese Feb 08 '21 at 04:06
  • guys, I update my question with code where I want to remove element –  Feb 08 '21 at 04:06
  • 1
    @DrewReese ```delete newCart[action.id]``` Yess.......this works for me. Thanks dude –  Feb 08 '21 at 04:07

2 Answers2

1

Actually delete keyword is not designed for doing this task. Also, the idea behind the reducer is to make a new state so copying state and then deleting an element is something you must try to do in proxied packages such as immer not js itself.

here are some tips for working with objects as there are many number of questions about state change with objects.

const state = { isActive: true, props: { userId: {} } }
Object.keys(state) // ['isActive', 'props']
Object.entries(state) // [['isActive', true], ['props', { userId: {} }]]
Object.keys(state).map((key, index) => state[key]) // // [true, { userId: {} }]

as I mentioned deleting doesn't play a good role here instead the better way to change sub-part object is using immer, or filter


const newCart = Object.keys(state.cart).filter(() => state.cart[action.id].quantity !== 1)
amirhe
  • 2,186
  • 1
  • 13
  • 27
  • I'm not sure I follow the logic of `delete` not being designed for this task, it is literally its purpose to remove a key-value from an object. Also, `Object.keys(state.cart)` returns an array of *just* the object's keys. Sure, you can filter the key from the array, but now the `newCart` state is mutated to an array and the values weren't persisted to the next state. – Drew Reese Feb 08 '21 at 05:22
  • Hi @DrewReese, `delete` doest lots of prototypal things that are redundant here, it is [slow](https://stackoverflow.com/a/44008788/10321531) and accessing a key in that object has [perf issue](https://stackoverflow.com/a/41236408/10321531) – amirhe Feb 08 '21 at 07:14
  • I don't disagree these being valid points (good resources), but they are (a) rather old posts, in the JS/webdev timeline, and (b) each delete is a single atomic operation and not the most expensive operation for React. IMHO this falls fully in the premature-optimization bucket. I'll concede that instead of deleting the entry, setting the value to `undefined` is just as readable and potentially accomplishes the same result in a more performant manner. – Drew Reese Feb 08 '21 at 16:47
  • I agree with you @DrewReese, setting undefined is a better solution, but we should be careful in mapping in presentational component e.g. filtering undefined value or handle it in a component (`return null`). From a personal understanding, I guess browser engines optimize and improve their speed on functions which is dominant in the web, such as string concatenation. – amirhe Feb 09 '21 at 03:05
0

You can try this logic, this is works for my case:

      const reducer = (state = initialState, action) => {
       case actionTypes.QUANTITY_COUNT:
            const newCart = {...state.cart};
            if (newCart[action.id].quantity === 1){
                  delete newCart[action.id]
                 
              }
}
Alamin
  • 1,878
  • 1
  • 14
  • 34