score:9

Accepted answer

it is happening because your reducer function is not a pure function, it should not be having any asynchronous calls.

something like this should work. it will fix the error you are getting

const products = createslice({
    name: "products",
    initialstate: {
        products: []
    },
    reducers: {
        reducer2: (state, { payload }) => {
                return { products: [...state.products, ...payload]}
         })

      }
    }
});

and api should be called outside

const fetchproducts = () => {

   axios.get('myurl')
     .then(response => {
        //console.log(response.data.products);
        store.dispatch(products.actions.reducer2(response.data.products))
   })
};

ps: haven't tried running above code, you may have to make modifications as per your need.

score:27

i would prefer to use createasyncthunk for api data with extrareducers

let assume this page name is productslice.js

import { createslice,createselector,payloadaction,createasyncthunk,} from "@reduxjs/toolkit";

export const fetchproducts = createasyncthunk(
  "products/fetchproducts", async (_, thunkapi) => {
     try {
        //const response = await fetch(`url`); //where you want to fetch data
        //your axios code part.
        const response = await axios.get(`url`);//where you want to fetch data
        return await response.json();
      } catch (error) {
         return thunkapi.rejectwithvalue({ error: error.message });
      }
});

const productsslice = createslice({
   name: "products",
   initialstate: {
      products: [],
      loading: "idle",
      error: "",
   },
   reducers: {},
   extrareducers: (builder) => {
      builder.addcase(fetchproducts.pending, (state) => {
        state. products = [];
          state.loading = "loading";
      });
      builder.addcase(
         fetchproducts.fulfilled, (state, { payload }) => {
            state. products = payload;
            state.loading = "loaded";
      });
      builder.addcase(
        fetchproducts.rejected,(state, action) => {
            state.loading = "error";
            state.error = action.error.message;
      });
   }
});


export const selectproducts = createselector(
  (state) => ({
     products: state.products,
     loading: state.products.loading,
  }), (state) =>  state
);
export default productsslice;

in your store.js add productsslice: productsslice.reducer in out store reducer.

then for using in component add those code ... i'm also prefer to use hook

import { useselector, usedispatch } from "react-redux";

import {
  fetchproducts,
  selectproducts,
} from "path/productslice.js";

then last part calling those method inside your competent like this

const dispatch = usedispatch();
const { products } = useselector(selectproducts);
react.useeffect(() => {
   dispatch(fetchproducts());
}, [dispatch]); 

and finally, you can access data as products in your component.


Related Query

More Query from same tag