I countered an undefined data from when i get all product form backend I using React for frontend and redux toolkit for handle global state and NodeJS + express JS for backend and database monogodb on atlas cloud
backend:
router.get(
"/get-all-products",
catchAsyncErrors(async (req, res, next) => {
try {
const products = await Product.find();
res.status(201).json({
success: true,
products,
});
} catch (error) {
return next(new ErrorHandler(error, 400));
}
})
);
reducer:
import { createReducer } from "@reduxjs/toolkit";
const initialState = {
isLoading: true,
};
export const productReducer = createReducer(initialState, {
getAllProductsRequest: (state) => {
state.isLoading = true;
},
getAllProductsSuccess: (state, action) => {
state.isLoading = false;
state.allProducts = action.payload;
},
getAllProductsFailed: (state, action) => {
state.isLoading = false;
state.error = action.payload;
},
});
action:
export const getAllProducts = () => async (dispatch) => {
try {
dispatch({
type: "getAllProductsRequest",
});
const { data } = await axios.get(`${server}/product/get-all-products`);
dispatch({
type: "getAllProductsSuccess",
payload: data.products,
});
} catch (error) {
dispatch({
type: "getAllProductsFailed",
payload: error.response.data.message,
});
}
};
Store:
import { configureStore } from '@reduxjs/toolkit';
import { userReducer } from './reducers/user';
import { sellerReducer } from './reducers/seller';
import { productReducer } from './reducers/product';
import { eventReducer } from './reducers/event';
const Store = configureStore({
reducer: {
user: userReducer,
seller: sellerReducer,
products: productReducer,
events: eventReducer,
},
});
jsx page :
import { useState, useEffect } from "react";
import styles from "../styles/styles";
import { useSearchParams } from "react-router-dom";
import ProductCard from "../components/Route/productCard/ProductCard";
import Header from "../components/layout/Header";
import Loader from "../components/layout/Loader";
import Footer from "../components/layout/Footer";
import { useSelector } from "react-redux";
const ProductsPage = () => {
const [searchParams] = useSearchParams();
const categoryData = searchParams.get("category");
const { allProducts, isLoading } = useSelector((state) => state.products);
const [data, setData] = useState([]);
useEffect(() => {
if (categoryData === null) {
const d = allProducts;
setData(d);
console.log(d);
} else {
const d =
allProducts && allProducts.filter((i) => i.category === categoryData);
setData(d);
}
// window.scrollTo(0,0);
}, [allProducts]);
return (
<>
{isLoading ? (
<Loader />
) : (
<div>
<Header activeHeading={3} />
<br />
<br />
<div className={`${styles.section}`}>
<div className="grid grid-cols-1 gap-[20px] md:grid-cols-2 md:gap[25px] lg:grid-cols-4 lg:gap-[25px] xl:grid-cols-5 xl:gap-[30px] mb-12">
{data &&
data.map((i, index) => <ProductCard data={i} key={index} />)}
</div>
{data && data.length === 0 ? (
<h1 className="text-center w-full pb-[100px] text-[20px]">
No Products Found !
</h1>
) : null}
</div>
<Footer />
</div>
)}
</>
);
};
export default ProductsPage;
Solution ------------
const dispatch = useDispatch();
useEffect(() => {
dispatch(getAllProducts());
}, [dispatch]);
return (
<>
{isLoading ? (
<Loader />
) : (
<div>
<Header activeHeading={3} />
<br />
<br />
<div className={`${styles.section}`}>
<div className="grid grid-cols-1 gap-[20px] md:grid-cols-2 md:gap[25px] lg:grid-cols-4 lg:gap-[25px] xl:grid-cols-5 xl:gap-[30px] mb-12">
{allProducts &&
allProducts.map((i, index) => (
<ProductCard data={i} key={index} />
))}
</div>
{allProducts && allProducts.length === 0 ? (
<h1 className="text-center w-full pb-[100px] text-[20px]">
No Products Found !
</h1>
) : null}
</div>
<Footer />
</div>
)}
</>
);
};
i need to get raid of this error and know why it's happen
201 Created
is the wrong response status for your GET request. 200 OK
would be much more appropriate and is already the default for res.json()
.
res.json({ products });
success: true
is totally unnecessary. If anything fails, your server will respond with an error response status (4xx
/ 5xx
)
What you're trying to do with the category filter is much more easily achieved using a memo hook
You aren't checking for errors
const [searchParams] = useSearchParams();
const categoryData = searchParams.get("category");
const {
allProducts,
isLoading,
error
} = useSelector((state) => state.products);
const data = useMemo(
() =>
categoryData
? allProducts.filter(({ category }) => category === categoryData)
: allProducts,
[allProducts, categoryData]
);
if (error) {
return <p className="warn">{error}</p>;
}
Note: there are no useState
or useEffect
hooks and most importantly no console.log()
! If you want to debug, use debugging tools.
Also ensure you define the initial state for allProducts
as an array so you avoid any errors around .map()
or .filter()
.
const initialState = {
isLoading: true,
allProducts: [], // 👈 initial empty array
};