React HTTP Request with Axios and Redux Thunk Tutorial

In this tutorial, we will learn how to make asynchronous HTTP requests in React using Redux createSlice, createAsyncThunk middleware, and Axios library.

Redux reducers are awesome and let you create a new state. However, for making an asynchronous request in React Redux, you need to rely on the createAsyncThunk middleware that works with extra reduces and builder callback notation.

Redux Thunk middleware calls action creators that return a function rather than an action object. The thunk function accepts the store’s dispatch method, which can be used to dispatch regular synchronous actions inside the function’s body after the asynchronous operations are executed.

The thunk action creator has a plain action creator that offers pending, fulfilled, and rejected cases that you call inside the extraReducer object using builder callback notation.

This guide will throw light on using createAsyncThunk and show you its use case in React Reux app.

React Redux HTTP Request with Async Thunk Middleware Tutorial

  • Step 1: Donwload React App
  • Step 2: Install React Redux Modules
  • Step 3: Create Reducer Slice
  • Step 4: Add Reducer to Store
  • Step 5: Bind Provider to App
  • Step 6: Handle Async Response
  • Step 7: Update App Js File
  • Step 8: Run React Project

Donwload React App

In the first step, you require to run the given command from the terminal, it will install a brand new react app.

npx create-react-app react-dev
cd react-dev

Here is the project’s folder structure for React redux thunk example.

React redux thunk example

Install React Redux Modules

You have to install the react-redux, redux toolkit, Axios, and bootstrap packages using the given commands.

npm install react-redux @reduxjs/toolkit axios bootstrap

Create Reducer Slice

In the src folder, make the features/ folder, then make the postsSlice.js file, then in this file, you have to add the given code.

We are creating the postsSlice using the createSlice module. Define the name of the slice, and define the initial state and the reducers object.

In the extraReducers object pass the builder parameter, and set the pending, idle, and error state using the getPosts action creator function.

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

export const getPosts = createAsyncThunk("posts/getPosts", async () => {
  const response = await axios.get(
    "https://jsonplaceholder.typicode.com/posts"
  );
  return response.data;
});

export const postsSlice = createSlice({
  name: "posts",
  initialState: {
    data: [],
    loading: "idle",
    error: null,
  },
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(getPosts.pending, (state, action) => {
      if (state.loading === "idle") {
        state.loading = "pending";
      }
    });

    builder.addCase(getPosts.fulfilled, (state, action) => {
      if (state.loading === "pending") {
        state.data = action.payload;
        state.loading = "idle";
      }
    });

    builder.addCase(getPosts.rejected, (state, action) => {
      if (state.loading === "pending") {
        state.loading = "idle";
        state.error = "Error";
      }
    });
  },
});

export default postsSlice.reducer;

Add Reducer to Store

Next up you have to create the src/app/store.js file; In this file set the postsReducer in the reducer object for invoking the redux store.

import { configureStore } from "@reduxjs/toolkit";
import postsReducer from "../features/postsSlice";

export default configureStore({
  reducer: {
    posts: postsReducer,
  },
});

Bind Provider to App

Open the index.js file; here you have to import the store and provider modules and wrap the App component with the Provider tag.

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import store from "./app/store";
import { Provider } from "react-redux";

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

Handle Async Response

Create the components folder, then create the Post.js file, in this file add the given code. By using the given code, you can display the posts list on the browser.

import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getPosts } from "../features/postsSlice";

const Cards = ({ data }) => {
  return (
    <div
      className="col-lg-12 mb-3"
      key={data.id}
    >
      <div className="card">
        <div className="card-body">
          <h5 className="card-title">{data.title}</h5>
          <p className="card-text">{data.body}</p>
        </div>
      </div>
    </div>
  );
};

function Post() {
  const dispatch = useDispatch();
  const { data, loading, error } = useSelector((state) => state.posts);

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

  let DATA;

  if (loading === "pending") {
    DATA = (
      <div className="d-flex justify-content-center">
        <div className="spinner-border" role="status">
          <span className="visually-hidden">Loading...</span>
        </div>
      </div>
    );
  }
  if (loading === "idle") {
    DATA = data.map((res) => {
      return <Cards data={res} key={res.id} />;
    });
  }
  if (error !== null) {
    DATA = (
      <div className="alert alert-danger" role="alert">
        {error}
      </div>
    );
  }

  return <div className="row">{DATA}</div>;
}

export default Post;

Update App Js File

In the App.js file add the bootstrap CSS path, import the App.css, and most importantly the Post component.

import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
import "./App.css";
import Post from "./components/Post";

function App() {
  return (
    <div className="container">
      <div className="d-flex text-center border-bottom pt-2 pb-2 mb-5">
        <div className="p-2 flex-grow-1">
          <h2>React Redux Async Api Call Example</h2>
        </div>
      </div>
      <Post />
    </div>
  );
}

export default App;

Run React Project

We can run the given command, and use the URL to view the app on the browser.

npm start
http://localhost:3000

React HTTP Request with Axios and Redux Thunk Tutorial

Conclusion

In this guide, we have seen and learned how to use Redux Thunk middleware to load the data by making the asynchronous HTTP request in React Redux using extra reducer and builder callback notation.

You can download the complete code of this guide from here.