In this blog, we will have a quick description on how to use the Thunk middleware in the Redux toolkit with React
Redux Thunk is included by default, allowing createAsyncThunk to perform delayed, asynchronous logic before sending the processed result to the reducers.
A good knowledge about Redux is required to understand Redux toolkit Thunk
Import createAsyncThunk from the reduxToolkit
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"
const initialState = {
users: [],
isloading: false
}
Creating Async Logic using createAsyncThunk
import { Endpoints } from "../App";
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"
const initialState = {
users: [],
isloading: false
}
export const GetAllUsers = createAsyncThunk("forms/allusers",
async (thunkAPI) => {
try {
let res = await fetch(Endpoints.getAllUsers)
console.log(res)
return res
} catch (error) {
return thunkAPI.rejectWithValue({ error: error });
}
})
Aysnc Requests are created with createAsyncThunk, it accepts different parameters an action type string, a callback function which is also called as Payload Creator, and an options object.
In our case, the “forms/allusers” is the action type string. When the async action is dispatched the createAsyncThunk creates the three promise lifecycle pending, fulfilled, rejected using the action type string as the prefix.
The async thunk dispatches the forms/allusers/pending lifecycle action type on the initial call. The payloadCreator returns the result or error.
When there is an error forms/allusers/rejected action type is dispatched. We need to return the error and use thunkAPI.rejectWithValue for the error handling.
If the action call is successful forms/users/fulfilled are dispatched.
The Three Lifecycle action explained above is handled in the extraReducers. What we usually do in the API calls is, set the response to the state and set the loading state. We do the same with the extraReducers with the redux store.
export const formSlice = createSlice({
name: "forms",
initialState,
reducers: {
onChangevalues: (state, action) => {
state.formData = action.payload
},
submitFormData: (state, action) => {
state.submitData.push(state.formData)
state.formData = { email: "", name: "" }
},
},
extraReducers(builder) {
builder
.addCase(GetAllUsers.pending, (state, action) => {
state.isloading = true
})
.addCase(GetAllUsers.fulfilled, (state, action) => {
state.users = action.payload
state.isloading = false
})
.addCase(GetAllUsers.rejected, (state, action) => {
state.isloading = false
})
}
})
In this extraReducers we will specify the change to be done when lifecycle action dispatches. In our case we will set isloading to true. In the pending fulfilled case, we will set the response to the users state and isloading state to false, and finally in rejected case we will set the isloading state to false
Dispatching actions in the Components
By using useSelector and useDispatch from react-redux, we can read the state from a Redux store and dispatch any action from a component, respectively.
import { useDispatch, useSelector } from 'react-redux';
import { GetAllUsers } from './Redux/appSlice'
function App() {
const dispatch = useDispatch()
const { isloading, users } = useSelector((state) => state.forms)
useEffect(() => {
dispatch(GetAllUsers())
}, [])
if (isloading) return <h1>loading...</h1>
return (
<>
{users.map((item, index) => (
<h1>{item.title}</h1>
))}
</>
);
}
No Comment! Be the first one.