javascriptreactjsreduxreact-reduxredux-toolkit

Facing error: Uncaught RangeError - Maximum call stack size exceeded


When I click "Add to cart" button, I get an error

Uncaught RangeError: Maximum call stack size exceeded

in my application. After investigating, it appears to be related to the handleAddCart function in the Product.js file. It seems there might be an unintentional infinite recursion happening within this function.

I tried every possible solution which came in my mind and I did fix it.

As I am learning redux-toolkit please fixed my error. Your help will be kindly appreciated

Here is my code:

productSlice.js:

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios from "axios";

export const fetchProduct = createAsyncThunk("fetchProduct", async () => {
  try {
    const res = await axios.get("https://dummyjson.com/products");
    const data = await res.data.products;
    return data;
  } catch (error) {
    console.log(error);
    throw error;
  }
});

const initialState = {
  products: [],
  isLoading: false,
  isError: false,
};

const productSlice = createSlice({
  name: "product",
  initialState,
  reducers: {
    setProduct: (state, action) => {
      state.products = action.payload;
    },
  },
  extraReducers: (builder) => {
    builder.addCase(fetchProduct.pending, (state, action) => {
      state.isLoading = action.payload;
    });
    builder.addCase(fetchProduct.fulfilled, (state, action) => {
      state.products = action.payload;
    });
    builder.addCase(fetchProduct.rejected, (state, action) => {
      console.log("Error:", action.payload);
      state.isError = true;
    });
  },
});

export const { setProduct } = productSlice.actions;

export default productSlice.reducer;

cartSlice.js:

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  cart: [],
};

const cartSlice = createSlice({
  name: "cart",
  initialState,
  reducers: {
    addToCart: (state, action) => {
      state.cart.push(action.payload);
    },
    removeFromCart: (state, action) => {
      return state.filter((item) => item.id !== action.payload);
    },
    incrementItemInCart: (state, action) => {},
    decrementItemInCart: (state, action) => {},
  },
});

export const {
  addToCart,
  removeFromCart,
  incrementItemInCart,
  decrementItemInCart,
} = cartSlice.actions;

export default cartSlice.reducer;

store.js:

import { configureStore } from "@reduxjs/toolkit";
import cartReducer from "./slice/cartSlice";
import productReducer from "./slice/productSlice";

export const store = configureStore({
  reducer: {
    cart: cartReducer,
    product: productReducer,
  },
});

Product.js:

import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { fetchProduct } from "../redux/slice/productSlice";
import { Link } from "react-router-dom";
import "./style.css";
import Navbar from "./Navbar";

const Product = () => {
  const dispatch = useDispatch();
  const products = useSelector((state) => state.product.products);

  useEffect(() => {
    dispatch(fetchProduct());
  }, [dispatch]);

  const getPriceAfterDiscount = (price, dis) => {
    var p = price - price * (dis / 100);
    return p.toFixed(2);
  };

  const getFirstLine = (text) => {
    if (!text) return "";
    return text.length > 50 ? text.substring(0, 50) + "..." : text;
  };

  const handleAddCart = (item) => {
    dispatch(handleAddCart(item));
  };

  return (
    <>
      <Navbar />
      <div className="products">
        <h2>Welcome to redux toolkit store</h2>
        <h2>Products</h2>
        <div className="products-wrapper">
          {products.map((item) => (
            <div className="product-card">
              <div className="badge">Hot</div>
              <div className="product-tumb">
                <img src={item.thumbnail} alt="" />
              </div>
              <div className="product-details">
                <span className="product-category">{item.category}</span>
                <h4>
                  <Link style={{ fontSize: "14px" }} href="">
                    {item.title}
                  </Link>
                </h4>
                <p style={{ fontSize: "8px", margin: 0 }}>
                  {getFirstLine(item.description)}
                </p>
                <div className="product-bottom-details">
                  <div className="product-price">
                    <small>${item.price}</small>$
                    {getPriceAfterDiscount(item.price, item.discountPercentage)}
                  </div>
                  <div className="product-links">
                    <button onClick={() => handleAddCart(item)}>
                      Add to cart
                    </button>
                  </div>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
};

export default Product;

Solution

  • You are calling handleAddCart() in handleAddCart() recursive. The error is thrown because handleAddCart() is called infinite times. At some point the browser hits a limit.