I am new to the redux toolkit, but after long research, I managed to write this configuration for the redux toolkit to fetch data from my backend express API. Can anyone please guide me if I am going right?
Should I use createAsyncThunk or this configuration is also correct?
store.js
import { configureStore } from "@reduxjs/toolkit";
import productReducer from "./features/productSlice";
export const store = configureStore({
reducer: {
products: productReducer,
},
});
productSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
products: [],
isLoading: false,
error: null,
};
export const productsSlice = createSlice({
name: "products",
initialState,
reducers: {
startLoading: (state) => {
state.isLoading = true;
},
hasError: (state, action) => {
state.error = action.payload;
state.isLoading = false;
},
allProductsSuccess: (state, action) => {
state.products = action.payload;
state.isLoading = false;
},
},
});
export default productsSlice.reducer;
productActions.js
import axios from "axios";
import { productsSlice } from "./productSlice";
const { allProductsSuccess, startLoading, hasError } = productsSlice.actions;
export const fetchProducts = () => async (dispatch) => {
dispatch(startLoading());
try {
const { data } = await axios.get("/api/v1/products");
dispatch(allProductsSuccess(data.products));
} catch (e) {
dispatch(hasError(e?.response?.data?.message));
}
};
Home.js (Component)
const { products, isLoading } = useSelector((state) => state.products);
console.log(products, isLoading)
useEffect(() => {
dispatch(fetchProducts());
}, []);
Thanks!
Is it correct? Sure, it looks like it would compile and run and do what you want.
Is it the recommended implementation? Not exactly. Using the createAsyncThunk
utility you can cut down on a little of the boilerplate/repetitive code. You can effectively "merge" the productSlice.js
and productActions.js
files since all the related actions can be exported from the productSlice.js
file. createAsyncThunk
generates the "pending"/"success"/"error" actions for you.
Example:
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
export const fetchProducts = createAsyncThunk(
"products/fetchProducts",
async (_, thunkAPI) => {
try {
const { data } = await axios.get("/api/v1/products");
return data;
} catch (e) {
return thunkAPI.rejectWithValue(e?.response?.data?.message);
}
}
);
const initialState = {
products: [],
isLoading: false,
error: null,
};
const productsSlice = createSlice({
name: "products",
initialState,
extraReducers: builder => {
builder
.addCase(fetchProducts.pending, (state) => {
state.isLoading = true;
})
.addCase(fetchProducts.fulfilled, (state, action) => {
state.products = action.payload.products;
state.isLoading = false;
})
.addCase(fetchProducts.rejected, (state, action) => {
state.error = action.payload;
state.isLoading = false;
});
},
});
export default productsSlice.reducer;