Search code examples
javascriptreduxreact-reduxredux-toolkit

Increasing count in reducer of createSlice Redux-Toolkit


I'm trying to increase the count inside the reducer function for an object. Here in the action addItem, I'm trying to increase the count if the item added is already present in the store.

import { createSlice, current } from "@reduxjs/toolkit";
import React from "react";

const cartSlice = createSlice({
  name: "cart",
  initialState: {
    items: [],
  },
  reducers: {
    addItem: (state, action) => {
      let a = 0;
      current(state.items).map((item) => {
        console.log(item, "hey there");
        if (item === action.payload) {
          console.log("Matched");
          console.log("Count1 is", ++item.card.info.count);
          item.card.info.count = item.card.info.count + 1;
          console.log("Count2 is", item.card.info.count);
          a = 1;
          return;
        }
      });
      if (a == 0) {
        state.items.push(action.payload);
      }
    },
    removeItem: (state, action) => {
      state.items.pop();
    },
    clearCart: (state, action) => {
      state.items.length = 0;
    },
  },
});

export const { addItem, removeItem, clearCart } = cartSlice.actions;

export default cartSlice.reducer;

I'm attaching the console output below.

{card: {…}} 'hey there'
cartSlice.js:15 Matched
cartSlice.js:16 Count1 is 1
cartSlice.js:18 Count2 is 0
cartSlice.js:13 {card: {…}} 'hey there'
cartSlice.js:15 Matched
cartSlice.js:16 Count1 is 1
cartSlice.js:18 Count2 is 0
cartSlice.js:13 {card: {…}} 'hey there'
cartSlice.js:15 Matched
cartSlice.js:16 Count1 is 1
cartSlice.js:18 Count2 is 0
cartSlice.js:13 {card: {…}} 'hey there'
cartSlice.js:15 Matched
cartSlice.js:16 Count1 is 1
cartSlice.js:18 Count2 is 0
cartSlice.js:13 {card: {…}} 'hey there'
cartSlice.js:15 Matched
cartSlice.js:16 Count1 is 1
cartSlice.js:18 Count2 is 0

Provide me some suggestion that what I'm doing wrong here.


Solution

  • The current utility only gets you the current value of the state, but it isn't the draft state you should be updating though.

    The current function from the immer library, which takes a snapshot of the current state of a draft and finalizes it (but without freezing). Current is a great utility to print the current state during debugging, and the output of current can also be safely leaked outside the producer.

    In essence it's a copy of the state, not the actual state, so any updates/mutations/etc to the copy will have absolutely no effect on the actual Redux state.

    The common practice is to search the array first for the matching item you with to update, and if it is found, update it (mutably), otherwise append it to the array.

    Example:

    addItem: (state, action) => {
      const item = state.items.find(
        item => item.someProperty === action.payload.someProperty
      );
    
      if (item) {
        item.card.info.count++;
      } else {
        state.items.push(action.payload);
      }
    },