Redux Thunk Middleware In Redux-Toolkit with async await
Today we’ll learn how to use Redux Thunk middleware in Redux Toolkit with async await
You can read this article on Medium
So, we’ll learn how to use redux-thunk with an example. We’ll make the get request, fetch the data, and display the data using async await.
So first create the react-app
npx create-react-app redux-thunk
Install react-redux and redux-toolkit
npm i react-redux
npm i @reduxjs/toolkit
After that let's set up the store
Create a folder redux inside the src folder and create a file postSlice.js
Inside the postSlice,
Import
import { createSlice,createAsyncThunk } from "@reduxjs/toolkit";
Initialize the state
const initialState = {
post:[],
error:'',
loading:false
}
Define the reducer using createSlice
const postSlice = createSlice({
name: 'posts',
initialState,
reducers:{},
});
Let’s export the reducer
export default postSlice.reducer
export const getPost = (state) => state.postReducer.post;
export const getLoading = (state) => state.postReducer.loading;
Here we are defining the?getPost?and?getLoading?functions these returns the desired state. make sure you use the same name for (state) that you have used inside the store for the reducer.
Here I have used the postReducer and the same name for the store.
Create the store inside the src folder
Now, let’s move to the main logic
import { createSlice,createAsyncThunk } from "@reduxjs/toolkit";
const GET_POST_URL= "https://jsonplaceholder.typicode.com/posts";
const initialState = {
post:[],
error:'',
loading:false
}
// fetch the post
export const fetchPosts = createAsyncThunk(
'posts/fetchPosts', // use the slice name
async () => {
const response = await fetch(GET_POST_URL)
const data = await response.json();
return data
}
)
const postSlice = createSlice({
name: 'posts',
initialState,
reducers:{},
extraReducers:(builder)=>{
builder
.addCase(fetchPosts.pending,(state)=>{
state.loading=true
})
.addCase(fetchPosts.fulfilled,(state,action)=>{
state.loading=false
state.post=action.payload
})
.addCase(fetchPosts.rejected,(state,action)=>{
state.loading=false
state.error=action.error.message
})
}
});
export default postSlice.reducer;
export const getPost = (state) => state.postReducer.post;
export const getLoading = (state) => state.postReducer.loading;
Let’s break it down into simple steps
Create the function using createAsyncThunk
// fetch the post
export const fetchPosts = createAsyncThunk(
'posts/fetchPosts',// use the slice name
async () => {
const response = await fetch(GET_POST_URL)
const data = await response.json();
return data
}
)
createAsyncThunk?accepts three parameters: a string action?type?value, a?payloadCreator?callback, and an?options?object.
领英推è
A string that will be used to generate additional Redux action type constants, representing the lifecycle of an async request:
For example, a?type?argument of?'post/fetchPosts'?will generate these action types:
- pending:?'post/fetchPosts/pending'?promise pending
- fulfilled:?'post/fetchPosts/fulfilled'?promise fulfilled
- rejected:?'post/fetchPosts/rejected'?promise rejected
# Callback function
A callback function that should return a promise containing the result of some asynchronous logic.
Here are simply returning the data.
So while we are using thunk middleware so let’s define the extra reducer
# extraReducers
extraReducers?allows?createSlice?to respond to other action types besides the types it has generated.
const postSlice = createSlice({
name: 'posts',
initialState,
reducers:{},
extraReducers:(builder)=>{
builder
.addCase(fetchPosts.pending,(state)=>{
state.loading=true
})
.addCase(fetchPosts.fulfilled,(state,action)=>{
state.loading=false
state.post=action.payload
})
.addCase(fetchPosts.rejected,(state,action)=>{
state.loading=false
state.error=action.error.message
})
}
});
# Builder: This builder notation is also the only way to add matcher reducers and default case reducers to your slice.
Here we have added three different cases:
- if fetchPosts.pending then set the loading true
- if fetchPosts.fulfilled then set the loading to false and post to the action.payload (we have returned the data in createAsynThunk).
- if fetchPosts.rejected then set the loading to false and set the error message to action.error.message
so let’s use these in our project to show the posts
Inside the postList.jsx we’ll show the posts
import React, { useState,useEffect } from 'react';
import {fetchPosts,getPost,getLoading} from '../redux/postSlice';
import {useSelector,useDispatch} from 'react-redux'
const PostList = () => {
const getPosts = useSelector(getPost);
const stateloading = useSelector(getLoading)
const dispatch = useDispatch()
useEffect(()=>{
dispatch(fetchPosts());
},[])
return (
<div className='post-wrapper'>
{
getPosts.map((post,index)=>(
<div className='single-post' key={index}>
<h4>{post.title}</h4>
<h6>{post.body}</h6>
</div>
))
}
</div>
)
}
export default PostList;
Here we have imported our fetchPosts , getPost, getLoading form the postSlice.
Let’s dispatch the function fetchPosts to make the request and get the data
if now you console the getPosts you will see the data
let’s map over the data and display it
return
( <div className='post-wrapper'>
{
getPosts.map((post,index)=>(
<div className='single-post' key={index}>
<h4>{post.title}</h4>
<h6>{post.body}</h6>
</div>
))
}
</div>
)
Hope you learn it ??
Happy coding!
want to give suggestions:-
have a look at?my portfolio
Email me at nidhisharma639593@gmail.com