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.
state.productis the state theproductReducerprovides, so if you are trying to access theproductsarray of theproductReducerthen it should bestate.product.products.or if you use object destructuring assignment
Alternatively, if this is the only state you could pass
productReducerdirectly to the store as the sole reducer, thenstate.productswould be correct.