Я создал редуктор продукта, действие продукта и домашний файл вместе с файлом констант (в основном для имени и хранения типа действия). В Home
я пытался получить products
из уже работающего бэкэнда.
Для этой функции я использовал хуки dispatch
и useSelector
.
Пока я использую крючок useSelector
в Home
, я получаю данные как неопределенные. Однако когда я проверил с помощью входа в консоль действие и файл продукта, данные присутствуют.
Я не знаю, почему происходит эта ошибка.
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.info(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
Продуктредуцер.js
import {
ALL_PRODUCT_FAIL,
ALL_PRODUCT_REQUEST,
ALL_PRODUCT_SUCCESS,
CLEAR_ERRORS,
} from "../constants/productContants";
export const productReducer = (state = { products: [] }, action ) => {
// console.info(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.info(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,
});
};
}
Магазин.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;
Я пытался получить данные из бэкэнда и использовал хуки useSelector()
и useDispatch()
. Данные извлекаются из серверной части, однако при использовании useSelector()
я получаю, что данные не определены, и не понимаю, почему это происходит.
🤔 А знаете ли вы, что...
JavaScript обеспечивает обработку ошибок с использованием конструкции try...catch.
const reducers = combineReducers({ product: productReducer, });
state.product
— это состояние, которое productReducer
обеспечивает, поэтому, если вы пытаетесь получить доступ к массиву products
productReducer
, то это должно быть state.product.products
.
const products = useSelector((state) => state.product.products);
или если вы используете назначение деструктуризации объекта
const { products } = useSelector((state) => state.product);
Альтернативно, если это единственное состояние, которое вы можете передать productReducer
непосредственно в хранилище в качестве единственного редуктора, то state.products
будет правильным.
const store = configureStore({
reducer: productReducer,
initalState
});
const products = useSelector((state) => state.products);