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 ></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 ></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
CodePudding user response:
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,
},
})