javascriptreactjsreduxreact-reduxredux-toolkit

I'm using Redux for data fetching and my extraReducers is not working cause I cant fetching data from products


I am using a free e-commerce API for data fetching and my getProducts action is working in products.jsx. When I console.log(response) this is working but I cant use useSelector for fetching data from products.jsx.

I think my extraReducers is not working cause I can't fetch data from products.

home.jsx

import { useDispatch, useSelector } from "react-redux";
import { useEffect, useState } from "react";
import { getProducts } from "../redux/products";
import Card from "../components/card";

function home() {
  const dispatch = useDispatch();

  const data = useSelector();
  console.log("data");

  //   const [arr, setArr] = useState([]);
  //   console.log(arr);

  //   useEffect(async () => {
  //     const response = await dispatch(getProducts());
  //     setArr(response.payload.data);
  //   }, []);

  useEffect(() => {
    dispatch(getProducts());
  }, [dispatch]);

  return (
    <div className="home">
      {/* {arr.map((data) => {
        return (
          <>
            <Card
              title={data.title}
              price={data.price}
              img={data.images[0]}
            ></Card>
          </>
        );
      })} */}
    </div>
  );
}

export default home;

products.jsx

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios from "axios";

export const getProducts = createAsyncThunk("getProducts", async () => {
  const response = await axios.get("https://api.escuelajs.co/api/v1/products");
  return response;
});

const initialState = {
  products: [],
};

export const productsSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(getProducts.fulfilled, (state, action) => {
      state.products = action.payload;
    });
  },
});

export const {} = productsSlice.actions;

export default productsSlice.reducer;

I implemented a second way for solving problem (you can see on home.jsx) but I want to use the useSelector hook.


Solution

  • Issue

    You have failed to pass a selector function to the useSelector hook to actually select the products state that is updated.

    const data = useSelector(); // <-- missing selector function!
    

    Solution Suggestion

    Assuming you have created the store as follows:

    import { configureStore, combineReducers } from '@reduxjs/toolkit';
    import productsReducer from '../path/to/productsSlice';
    // ... other imports ...
    
    const rootReducer = combineReducers({
      // ... other reducers
    
      // matching slice name property, i.e. "counter", is a convention,
      // but can be any valid Javascript identifier
      counter: productsReducer,
    });
    
    const store = configureStore({
      reducer: rootReducer,
    });
    

    Then the products "data" you are selecting is state.counter.products.

    const data = useSelector(state => state.counter.products);
    

    It's common to not rename the selected values to something else which can cause confusion.

    Examples:

    const products = useSelector(state => state.counter.products);
    

    or

    const { products } = useSelector(state => state.counter);