I created a product reducer, product action, and home file along with constants file (mainly to name and store the type of the action). In Home
I was trying to get the products
from the backend that is already working.
I used dispatch
and useSelector
hooks for that function.
While I am using useSelector
hook in the Home
I am getting data as undefined. However when I checked by console logging in the action and the product file there the data is present.
I don’t know why this error is happening.
Home.js
import React, { Fragment, useEffect } from 'react'
import Loader from "../layout/Loader/Loader";
import MetaData from "../layout/MetaData.js";
import ProductCard from './ProductCard.js';
import { CgMouse } from "react-icons/cg";
import "./Home.css";
import { clearErrors, getProduct } from "../../actions/productAction";
import { useSelector, useDispatch } from "react-redux";
const product = {
name: "Blue Tshirt",
images: [{ url: "https://i.ibb.co/DRST11n/1.webp" }],
price: "$3000",
_id: "aditya",
};
const Home = () => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(getProduct())
}, [dispatch]);
const data = useSelector((state) => state.products);
console.log(data);
// const { loading, error, products } = useSelector((state) => state.products);
return (
<div>
{/* <Fragment>
{loading ? (
<Loader />
) : ( */}
<Fragment>
<MetaData title="ECOMMERCE" />
<div className="banner">
<p>WELCOME TO ECOMMERCE</p>
<h1>FIND AMAZING PRODUCTS BELOW</h1>
<a href="#container">
<button>
Scroll<CgMouse />
</button>
</a>
</div>
<h2 className="homeHeading">Featured Products</h2>
<div className="container" id="container">
{/* {products && products.map((product)=>( */}
<ProductCard key={product._id} product={product}/>
{/* ))} */}
</div>
</Fragment>
{/* )} */}
{/* </Fragment> */}
</div>
)
}
export default Home
ProductReducer.js
import {
ALL_PRODUCT_FAIL,
ALL_PRODUCT_REQUEST,
ALL_PRODUCT_SUCCESS,
CLEAR_ERRORS,
} from "../constants/productContants";
export const productReducer = (state = { products: [] }, action ) => {
// console.log(action.payload);
switch(action.type){
case ALL_PRODUCT_REQUEST:
return {
loading: true,
product: [],
};
case ALL_PRODUCT_SUCCESS:
let obj = {
loading: false,
products: action.payload.products,
productsCount: action.payload.productsCount,
resultPerPage: action.payload.resultPerPage,
filteredProductsCount: action.payload.filteredProductsCount,
};
// console.log(obj);
return obj;
case ALL_PRODUCT_FAIL:
return {
loading: false,
error: action.payload,
};
case CLEAR_ERRORS:
return {
...state,
error: null,
};
default:
return state;
}
};
productActions.js
import axios from "axios";
import {
ALL_PRODUCT_FAIL,
ALL_PRODUCT_REQUEST,
ALL_PRODUCT_SUCCESS,
CLEAR_ERRORS,
} from "../constants/productContants";
// get all the products
export const getProduct = () => async (dispatch) => {
try {
dispatch({type:ALL_PRODUCT_REQUEST});
const {data} = await axios.get("/api/v1/products");
dispatch({
type: ALL_PRODUCT_SUCCESS,
payload: data,
});
} catch(error) {
dispatch({
type: ALL_PRODUCT_FAIL,
payload: error.response.data.message,
});
};
}
Store.js
import { configureStore } from '@reduxjs/toolkit';
import { combineReducers } from "redux";
import { productReducer } from './reducers/productReducer';
import thunk from "redux-thunk";
const reducers = combineReducers({
product: productReducer,
});
let initalState = {};
const store = configureStore({
reducer: reducers,
initalState
});
export default store;
I was trying to fetch the data from backend and was using useSelector()
and useDispatch()
hook. The data is being fetched from the backend however while using useSelector()
I am getting that the data is undefined and I don’t understand why this is happening.
2
Answers
state.product
is the state theproductReducer
provides, so if you are trying to access theproducts
array of theproductReducer
then it should bestate.product.products
.or if you use object destructuring assignment
Alternatively, if this is the only state you could pass
productReducer
directly to the store as the sole reducer, thenstate.products
would be correct.Hi There is typo
const data = useSelector((state)=>state.product);
you can also write like this:
const {loading,error,products} = useSelector((state)=>state.product);
your reducers name is product not products (typo Here)