Неопределенные данные при использовании перехватчика useSelector

Я создал редуктор продукта, действие продукта и домашний файл вместе с файлом констант (в основном для имени и хранения типа действия). В 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.


1
50
2

Ответы:

Решено
const reducers = combineReducers({
  product: productReducer,
});

state.product — это состояние, которое productReducer обеспечивает, поэтому, если вы пытаетесь получить доступ к массиву productsproductReducer, то это должно быть 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);

const data = useSelector((state)=>state.product);

вы также можете написать так:

const {loading,error,products} = useSelector((state)=>state.product);

имя вашего редуктора — это продукт, а не продукты (здесь опечатка)