skip to Main Content

my reducer function as per seen the code below, is getting called multiple times causing my incremention to be worng and increment by margins of 2.
i am running this in strictmode so i know it renders one more time to be safe. but it shouldnt affect the state/

export const ItemContext = createContext();
export const CartItemContext = createContext();

function reducer(state,action){
  if(action.type === "increment-quantity")
  {
    console.log(state[action.mealIndex][1]);
    state[action.mealIndex][1] +=1 ;
  }
  else if(action.type === "decrement-quantity")
  {

  }
  else if(action.type === "add-meal")
  {
      state = [...state,[action.meal,1]];
  }
  return state;
}


function App() {
  const [orderedMeals,dispatch] = useReducer(reducer,[]);
  const [openModal,setOpenModal] = useState(false);
  const [Quantity,setQuantity] = useState(0);

  const [isFetching,menu,setFetchedData,error]= useFetch(fetchMeals,[]);



  const onAddToCart = (meal) => {
    const mealFound = orderedMeals.find((mealPair) => {return mealPair[0] === meal;})
    const mealIndex = orderedMeals.indexOf(mealFound);
    if(mealFound === undefined)
    {
      dispatch({type:"add-meal",meal:meal})
    }
    else
    {
      dispatch({type:"increment-quantity",mealIndex:mealIndex});
    }
    setQuantity(Quantity+1);
  };

i dont know hwo to fix this please help thank.

2

Answers


  1. Issue

    It’s due to the direct mutation of the state in your reducer function. You should never mutate the state directly as it can lead to unexpected behavior. Instead, you should return a new state.

    Solution

    I’m using the map function to create a new array where the quantity of the required meal is incremented. It ensures that a new state is returned.

    function reducer(state, action) {
      switch (action.type) {
        case "increment-quantity":
          return state.map((item, index) =>
            index === action.mealIndex ? [item[0], item[1] + 1] : item
          );
        case "add-meal":
          return [...state, [action.meal, 1]];
        default:
          return state;
      }
    }
    
    Login or Signup to reply.
  2. The issue you’re facing is related to the fact that you are directly modifying the state in your reducer, which is an anti-pattern in React.

    React relies on immutability to properly detect and update the state. Directly modifying the state can lead to unexpected behaviours, especially when working with reducers and components.

    In your reducer function, when you modify the quantity like this:

    state[action.mealIndex][1] += 1;
    

    You are mutating the existing state, which can lead to issues with React’s state management and cause unexpected re-renders.

    To fix this issue, you should create a new state object or array when updating the state. Here’s an updated version of your reducer function:

    function reducer(state, action) {
      if (action.type === "increment-quantity") {
        return state.map((mealPair, index) =>
          index === action.mealIndex ? [mealPair[0], mealPair[1] + 1] : mealPair
        );
      } else if (action.type === "decrement-quantity") {
        // Handle decrement if needed
      } else if (action.type === "add-meal") {
        return [...state, [action.meal, 1]];
      }
      return state;
    }
    

    This way, you are creating a new array and new subarrays when updating the state. This follows the principles of immutability and ensures that React can properly track and update the state.

    Additionally, make sure to avoid side effects in your reducer and keep it as a pure function. If you need to perform asynchronous operations or side effects, consider using middleware like Redux Thunk or Redux Saga.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search