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
              }
}
13
  • 1
    You need to use cart.filter( (c) => c.id !== action.payload ), this logic for delete Commented Feb 8, 2021 at 3:50
  • 1
    It's a normal method for delete, if you have faced an error, then you need to show your code. Commented Feb 8, 2021 at 3:54
  • 1
    It's not working because cart is not an array of objects, but an object of objects based on your console.log Commented Feb 8, 2021 at 3:56
  • 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? Commented Feb 8, 2021 at 4:02
  • 1
    @DrewReese delete newCart[action.id] Yess.......this works for me. Thanks dude Commented Feb 8, 2021 at 4:07

2 Answers 2

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)
Sign up to request clarification or add additional context in comments.

4 Comments

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.
Hi @DrewReese, delete doest lots of prototypal things that are redundant here, it is slow and accessing a key in that object has perf issue
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.
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.
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]
                 
              }
}

1 Comment

OP's cart is clearly an object, for some reason, not an array. This answer doesn't fit the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.