Home > Blockchain >  Error: [Immer] An immer producer returned a new value *and* modified its draft. Either return a new
Error: [Immer] An immer producer returned a new value *and* modified its draft. Either return a new

Time:12-21

So, I am making this shopping cart in redux-toolkit, where user can't order more than the quantity available. So, my reducer function is like below for adding to cart.

import { createSlice } from "@reduxjs/toolkit";
import { FoodCartType } from "../../types";

type CartState = {
  cart: FoodCartType[];
};

const initialState: CartState = {
  cart: [],
};

export const foodcartSlice = createSlice({
  name: "foodcart",
  initialState,
  reducers: {
    addToCart: (state, action) => {
      console.log(action);
      if (state.cart.length === 0) {
        state.cart.push(action.payload);
      }
      const itemIndex = state.cart.findIndex(
        (item) => item.id === action.payload.id
      );

      if (itemIndex >= 0) {
        return {
          ...state,
          cart: state.cart.map((item) => {
            if (item.id === action.payload.id) {
              return {
                ...item,
                quantity: item.quantity   1,
                quantity_available: item.quantity_available - 1,
              };
            }
          }),
        };
      } else {
        return {
          ...state,
          cart: [
            ...state.cart,
            {
              ...action.payload.product,
              quantity: 1,
              quantity_available: action.payload.quantity_available - 1,
            },
          ],
        };
      }
    },
  },
});

export const { addToCart } = foodcartSlice.actions;

export default foodcartSlice.reducer;

When I click on the dispatch, on the component. I get the following error.

Unhandled Runtime Error Error: [Immer] An immer producer returned a new value and modified its draft. Either return a new value or modify the draft.

So, where I am doing the problem? if I just remove the itemIndex check part, items get pushed into the cart. But, other than that it is giving me this error. How should I rewrite this?

CodePudding user response:

Because your state.cart.push(action.payload); line modifies the value of state and later you return a new value.

You are allowed to do one, but not both at once. See writing reducers with immer

What you could do here: always modify. That's also far more readable.

export const foodcartSlice = createSlice({
  name: "foodcart",
  initialState,
  reducers: {
    addToCart: (state, action) => {
      console.log(action);
// you push later anyways, so you can also delete these lines
//      if (state.cart.length === 0) {
//        state.cart.push(action.payload);
//      }
      const itemIndex = state.cart.findIndex(
        (item) => item.id === action.payload.id
      );

      if (itemIndex >= 0) {
        state.cart[itemIndex].quantity  = 1
        state.cart[itemIndex].quantity_available -= 1
      } else {
        state.cart.push({
              ...action.payload.product,
              quantity: 1,
              quantity_available: action.payload.quantity_available - 1,
        })
      }
    },
  },
});
  • Related