0

I am trying to see if the ID already exist in the state json then update the count for that ID by 1.

export function cartReducer(state = {}, action) {
  switch (action.type) {
    case ADD_TO_CART:
      return {
        ...state, [action.payload._id]: {data: action.payload, count: 1}
      }

    default:
  }
  return state;
}

In state this is stored in cartList

Haris Uddin
  • 85
  • 2
  • 8

1 Answers1

2

Try this way:

export function cartReducer(state = {}, action) {
  switch (action.type) {
    case ADD_TO_CART:
      return {
        ...state,
        [action.payload._id]: {
          data: action.payload,
          count: state[action.payload._id] ? state[action.payload._id].count + 1 : 1,
        }
      }
    default:
      return state;
  }
}

Edit: Below a detailed answer your question in your comment

Let's assume you have already fetched data and your cartReducer has the following value :

{
  1: { data: { _id: 1, name: 'Evian Bottle 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
}

1. The user adds for the first time the item 7Up 1L in the cart. You dispatch the following action:

{
  type: 'ADD_TO_CART',
  payload: {
    _id: 3,
    name: '7Up 1L',
  }
}

Here how your reducer will process the new value:

First step

return {
  ...state,
  [action.payload._id]: {
    data: action.payload,
    count: state[action.payload._id] ? state[action.payload._id].count + 1 : 1,
  }
}

Second step

return {
  1: { data: { _id: 1, name: 'Evian 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
  [action.payload._id]: {
    data: action.payload,
    count: state[action.payload._id] ? state[action.payload._id].count + 1 : 1,
  }
}

Third step

return {
  1: { data: { _id: 1, name: 'Evian 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
  3: {
    data: { _id: 3, name: '7Up 1L' },
    count: state[3] ? state[3].count + 1 : 1,
  }
}

Fourth step

return {
  1: { data: { _id: 1, name: 'Evian 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
  3: {
    data: { _id: 3, name: '7Up 1L' },
    count: 1,
  }
}

2.Now your user wants to add another 7Up 1L in the cart. Dispatch of the action:

{
  type: 'ADD_TO_CART',
  payload: {
    _id: 3,
    name: '7Up 1L',
  }
}

Your reducer:

First step

return {
  ...state,
  [action.payload._id]: {
    data: action.payload,
    count: state[action.payload._id] ? state[action.payload._id].count + 1 : 1,
  }
}

Second step

return {
  1: { data: { _id: 1, name: 'Evian 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
  3: { data: { _id: 3, name: '7Up 1L' }, count: 1 },
  [action.payload._id]: {
    data: action.payload,
    count: state[action.payload._id] ? state[action.payload._id].count + 1 : 1,
  }
}

Third step

return {
  1: { data: { _id: 1, name: 'Evian 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
  3: { data: { _id: 3, name: '7Up 1L' }, count: 1 },
  3: {
    data: { _id: 3, name: '7Up 1L' },
    count: state[3] ? state[3].count + 1 : 1,
  }
}

Fourth step

return {
  1: { data: { _id: 1, name: 'Evian 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
  3: { data: { _id: 3, name: '7Up 1L' }, count: 1 },
  3: {
    data: { _id: 3, name: '7Up 1L' },
    count: 1 + 1,
  }
}

Fifth step

return {
  1: { data: { _id: 1, name: 'Evian 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
  3: { data: { _id: 3, name: '7Up 1L' }, count: 1 },
  3: {
    data: { _id: 3, name: '7Up 1L' },
    count: 2,
  }
}

Sixth step

return {
  1: { data: { _id: 1, name: 'Evian 1L' }, count: 1 },
  2: { data: { _id: 2, name: 'Coca Zero 1L' }, count: 1 },
  3: {
    data: { _id: 3, name: '7Up 1L' },
    count: 2,
  }
}

Hope it helps.


Edit 2: Answer to your 2nd question in the comment: What happens when I want to remove items from the cart ?

1. The user removes the Evian 1L from his cart. You dispatch the following action:

{
  type: 'REMOVE_FROM_CART',
  payload: {
    _id: 1,
  }
}

2. You reducer

export function cartReducer(state = {}, action) {
  switch (action.type) {
    case ADD_TO_CART:
      return {
        ...state,
        [action.payload._id]: {
          data: action.payload,
          count: state[action.payload._id] ? state[action.payload._id].count + 1 : 1,
        }
      }
      case REMOVE_FROM_CART: {
        const foundItem = state[action.payload._id];

        if (foundItem && foundItem.count > 1) {
          return {
            ...state,
            [action.payload._id]: {
              ...foundItem,
              count: foundItem.count - 1,
            }
          }
        }

        // In a immutable way - Avoid using the delete keyword
        return Object
          .keys(state)
          .filter(key => key != _id)
          .reduce((result, item) => ({ ...result, [item]: state[item] }), {});
    }
    default:
      return state;
  }
}

Edit 3: Answer to your 3rd question in the comment: What if the count has already reached 0 and we want to subtract one more item ?

The best way to do this would be: Directly in the component: Before this dispatch, check if the count is already at 0.

  1. If so, don't trigger this dispatch but another one that would allow you to display this message.
  2. Otherwise, trigger it.

In the current reducer, with the written code in this answer, you won't be able to find this ID so nothing to change :) Hope it helps!

yuantonito
  • 1,274
  • 8
  • 17
  • Thanks. It's working. I was trying to run a map and compare id's and then change the state, so it would be really amazing if you can explain what you did. – Haris Uddin Oct 30 '17 at 09:36
  • What I am trying to ask is that how does this line "state[action.payload._id]" knows that in state there is cartList and in that cartList has this object... because my first approach would be state.cartList and then loop though all the items until I find the correct one – Haris Uddin Oct 30 '17 at 09:40
  • I just edited my answer so you can have a detailed answer. – yuantonito Oct 30 '17 at 11:15
  • Thanks a lot.... you made it super easy to understand. you are awesome. – Haris Uddin Oct 30 '17 at 23:00
  • Sorry for bugging you... One last thing if I want to do subtract, I would follow the same process. But if I wanted to see if the count has reached 0 remove the item from the list how would I do that, in the light as you mentioned above? – Haris Uddin Oct 30 '17 at 23:34
  • @yuantonito Can you check this [question](https://stackoverflow.com/questions/60397123/how-to-check-item-in-favorite-list-redux), please? – Oliver D Feb 26 '20 at 13:26
  • Woaw, a super old thread and I didn't even see the question! Thanks @OliverD I added a very short answer but if you need more explanation, feel free to ask me! – yuantonito Feb 27 '20 at 16:09
  • I'm doing it yesterday, but I have some issues with it [here](https://stackoverflow.com/questions/60421126/store-not-updated-in-redux) can u please check it? – Oliver D Feb 27 '20 at 16:17