Uncaught TypeError: cart.map is not a function redux toolkit

Advertisements

I am receiving an error of Uncaught TypeError: cart.map is not a function

My cartSlice.js page:

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

const cartSlice = createSlice({
  name: "cart",
  initialState: {
    cart: [],
  },
  reducers: {
    addToCart: (state, action) => {
      const itemInCart = state.cart.find(
        (item) => item.id === action.payload.id
      );
      if (itemInCart) {
        itemInCart.quantity++;
      } else {
        state.cart.push({ ...action.payload, quantity: 1 });
      }
    },
    incrementQuantity: (state, action) => {
      const item = state.cart.find((item) => item.id === action.payload);
      item.quantity++;
    },
    decrementQuantity: (state, action) => {
      const item = state.cart.find((item) => item.id === action.payload);
      if (item.quantity === 1) {
        item.quantity = 1;
      } else {
        item.quantity--;
      }
    },
    removeItem: (state, action) => {
      const removeItem = state.cart.filter(
        (item) => item.id !== action.payload
      );
      state.cart = removeItem;
    },
  },
});

export const cartReducer = cartSlice.reducer;
export const { addToCart, incrementQuantity, decrementQuantity, removeItem } =
  cartSlice.actions;

My store.js page (where I configure my store):

import { configureStore, combineReducers } from "@reduxjs/toolkit";

import { cartReducer } from "./cartSlice";
import appApi from "../services/appApi";

import storage from "redux-persist/lib/storage";
import {
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from "redux-persist";

import productReducer from "./productSlice";
import customerReducer from "./customerSlice";
import userReducer from "./userSlice";
import thunk from "redux-thunk";
import packageReducer from "./packageSlice";

const persistConfig = {
  key: "root",
  storage,
  blackList: [appApi.reducerPath],
};

const rootReducer = combineReducers({
  [appApi.reducerPath]: appApi.reducer,
  products: productReducer,
  customers: customerReducer,
  cart: cartReducer,
  user: userReducer,
  packages: packageReducer,
});

const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }).concat(thunk, appApi.middleware),
});

export default store;

My index.js page (where I pass my store in the provider):

import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import store from "./redux/store";
import "./Admin/assets/css/App.css";
import { ChakraProvider } from "@chakra-ui/react";
import theme from "./Admin/theme/theme";
import { ThemeEditorProvider } from "@hypertheme-editor/chakra-ui";
import App from "./App";
import persistStore from "redux-persist/es/persistStore";
import { PersistGate } from "redux-persist/integration/react";

const persistedStore = persistStore(store);

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <ChakraProvider theme={theme}>
    <React.StrictMode>
      <ThemeEditorProvider>
        <Provider store={store}>
          <PersistGate loading={null} persistor={persistedStore}>
            <App />
          </PersistGate>
        </Provider>
      </ThemeEditorProvider>
    </React.StrictMode>
  </ChakraProvider>
);

My Cart.js page:

import Total from "../components/Shop/Total";
import CartItem from "../components/Shop/CartItem";
import { useSelector } from "react-redux";
import { Link, useNavigate } from "react-router-dom";
import Navbar from "../components/Shop/Navbar";
import Footer from "../components/Home/Footer";

function Cart() {
  const cart = useSelector((state) => state.cart);
  console.log(cart);
  const user = useSelector((state) => state.user);
  const navigate = useNavigate();

  return (
    <>
      <div className="mb-5">
        <Navbar />
      </div>
      <div className="cart">
        <div className="cart__left">
          <div>
            <h3>Shopping Cart</h3>
            {cart?.map((item) => (
              <CartItem
                key={item.id}
                id={item.id}
                name={item.name}
                price={item.price}
                quantity={item.quantity}
              />
            ))}
          </div>
        </div>

        <div className="cart__right">
          <Total />
          {user ? (
            <Link to="/checkout">
              <button
                className="btn btn-warning check-btn"
                style={{ width: "20rem", padding: 10 }}
              >
                Procceed To Checkout <i class="bi bi-wallet2"></i>
              </button>
            </Link>
          ) : (
            <Link to="/login">
              <button
                className="btn btn-warning check-btn"
                style={{ width: "20rem", padding: 10 }}
                onClick={() => navigate("/login")}
              >
                LogIn To Checkout <i class="bi bi-wallet2"></i>
              </button>
            </Link>
          )}
        </div>
      </div>
    </>
  );
}

export default Cart;

My CartItem.js page:

import {
  incrementQuantity,
  decrementQuantity,
  removeItem,
} from "../../redux/cartSlice";
import { useDispatch } from "react-redux";

function CartItem({ id, name, price, quantity = 0 }) {
  const dispatch = useDispatch();

  return (
    <div className="cartItem">
      <div className="cartItem__info">
        <p className="cartItem__title">{name}</p>
        <p className="cartItem__price">
          <small>R</small>
          <strong>{price}</strong>
        </p>
        <div className="cartItem__incrDec">
          <button onClick={() => dispatch(decrementQuantity(id))}>-</button>
          <p>{quantity}</p>
          <button onClick={() => dispatch(incrementQuantity(id))}>+</button>
        </div>
        <button
          className="cartItem__removeButton"
          onClick={() => dispatch(removeItem(id))}
        >
          Remove
        </button>
      </div>
    </div>
  );
}

export default CartItem;

My Total.js page:

import { useSelector } from "react-redux";

function Total() {
  const cart = useSelector((state) => state.cart);

  const getTotal = () => {
    let totalQuantity = 0;
    let totalPrice = 0;
    cart?.forEach((item) => {
      totalQuantity += item.quantity;
      totalPrice += item.price * item.quantity;
    });
    return { totalPrice, totalQuantity };
  };

  return (
    <div className="total">
      <h2 className="font-semibold fs-2">ORDER SUMMARY</h2>
      <div>
        <p className="total__p font-medium fs-5">
          total ({getTotal().totalQuantity} products) :{" "}
          <strong>R{getTotal().totalPrice}</strong>
        </p>
      </div>
    </div>
  );
}

export default Total;

I went to my shop page to try and add a product to my cart.

Shop.js page:

import React from "react";
import { motion } from "framer-motion";

import Navbar from "../components/Home/Navbar";
import Hero from "../components/Shop/Hero";
import ShopCard from "../components/Shop/ShopCard";

import { useNavigate } from "react-router-dom";
import { useSelector } from "react-redux";

const Shop = () => {
  const products = useSelector((store) => store.products);
  const navigate = useNavigate();
  const ProductShop = () => (
    <div className="shopping-cart" onClick={() => navigate("/cart")}>
      <div className="bg-white">
        {products?.map((product) => (
          <div key={product.id}>
            <ShopCard
              name={product.name}
              price={product.price}
              desc={product.desc}
            />
          </div>
        ))}
      </div>
    </div>
  );

  return (
    <motion.div
      id="main"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0, transition: { duration: 0.4 } }}
    >
      <Navbar />
      <Hero />
      {products?.length ? (
        ProductShop()
      ) : (
        <h1 className="fw-bold text-warning fs-3 text-center mt-3">
          Products not availabe
        </h1>
      )}
    </motion.div>
  );
};

export default Shop;

My ShopCard.js page:

import React from "react";
import { useDispatch } from "react-redux";
import { addToCart } from "../../redux/cartSlice";
import { AiOutlineShoppingCart } from "react-icons/ai";

const ShopCard = ({ id, name, price, desc }) => {
  const dispatch = useDispatch();
  return (
    <>
      <section style={{ backgroundColor: "#eee" }}>
        <div className="text-center container py-5">
          <div className="column">
            <div className="col-lg-4 col-md-12 mb-4">
              <div className="card">
                <div
                  className="bg-image hover-zoom ripple ripple-surface ripple-surface-light"
                  data-mdb-ripple-color="light"
                >
                  <a href="#!">
                    <div className="hover-overlay">
                      <div
                        className="mask"
                        style={{ backgroundColor: "rgba(251, 251, 251, 0.15)" }}
                      ></div>
                    </div>
                  </a>
                </div>
                <div className="card-body">
                  <h5 className="card-title mb-3 fw-bolder fs-3">{name}</h5>
                  <div className="mb-2 fs-5">
                    <h2>{desc}</h2>
                  </div>
                  <h6 className="mb-3 fw-bold fs-4">R{price}</h6>
                  <button
                    className="d-flex m-auto bg-warning text-white font-regular fs-5 align-items-center justify-content-center"
                    style={{ width: "100%", padding: 10 }}
                    type="button"
                    onClick={() => dispatch(addToCart({ id, name, price }))}
                  >
                    <AiOutlineShoppingCart fontSize={23} className="me-2" /> Add
                    to Cart
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
    </>
  );
};

export default ShopCard;

Then consoled log to see if it was working:

 const cart = useSelector((state) => state.cart);
  console.log(cart);

My consoled cart:

Object
cart
: 
Array(1)
0
: 
{name: 'Vegan Ham', price: '56', quantity: 4}
length
: 
1

Its working but its not showing it up in my cart page. I have been trying to fix this problem for days now and I don’t understand why it’s not working.

The error is coming from this piece of code:

           {cart?.map((item) => (
                  <CartItem
                    key={item.id}
                    id={item.id}
                    name={item.name}
                    price={item.price}
                    quantity={item.quantity}
                  />
                ))}

Any help would be appreciated. Thanks

>Solution :

const cart = useSelector((state) => state.xyz.cart);

xyz is the key that you set in the store for the value of cartReducer in your store.

export const store = configureStore({
  reducer: {
    xyz: cartReducer,
  },
})

Leave a ReplyCancel reply