Open In App

How to manage Loading & Error States when Fetching Data in Redux ?

Last Updated : 26 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

This article is about managing loading states and error states when fetching data in redux. I have used an API that returns a list of users. I will be using this API and redux to manage the loading states and error states.

07

Final Output

Prerequisites:

Approach:

  • Install the required packages, we are using axios to fetch data, react-redux and redux-tool kit , so install these packages.
  • We are using two components app.js and userComponent.jsx which renders list of users from the api.
  • We have redux store to manage the state and userSlice to handle and manage the users state.

Steps to create the project:

Step1: create the react app using the command

npx create-react-app react-loading-states
cd react-loading-states

Step2: Install the required dependencies

npm i axios
npm install @reduxjs/toolkit
npm install react-redux

Project Structure:

redux-states

Project Structure

The updated dependencies in package.json file looks like

redux-dependencies

project-dependencies

Example: To demonstrate managing loading states and error states while fetching data using react-redux

CSS
/* App.css */
.nav{
  display: flex;
  align-items: center;
  padding-left: 3vw;
  color: white;
  height: 8vh;
  background-color: rgb(83, 88, 105);
}
JavaScript
//App.js
import logo from "./logo.svg";
import "./App.css";
import UserComponent from "./user/UserComponent";

function App() {
    return (
        <div>
            <div className="nav">
                <p>Home</p>
            </div>
            <UserComponent />
        </div>
    );
}

export default App;
JavaScript
//userComponent.jsx
import React from 'react'
import { useDispatch, useSelector } from 'react-redux';
import { useEffect } from 'react';
import { fetchUsers } from './userSlice';

function UserComponent() {
    const dispatch = useDispatch();
    const user = useSelector((state) => state.user);
    useEffect(() => {
        dispatch(fetchUsers())
        console.log("users", user)
    }, [])
    return (
        <div>
            <h2>ALL USERS DETAILS</h2>
            {user?.loading && <div> loading....</div>}
            {!user?.loading && user?.users?.length > 0 ?

                <div>
                    <thead>
                        <tr>
                            <td><h4>Name</h4></td>
                            <td><h4>Email</h4></td>
                            <td><h4>UserName</h4></td>
                        </tr>
                    </thead>
                    <tbody>
                        {user?.users?.map((item) => (
                            <tr>
                                <td>{item?.name}</td>
                                <td>{item?.email}</td>
                                <td>{item?.username}</td>
                            </tr>
                        ))}
                    </tbody>
                </div> : <div>NO USER DATA AVAILABLE</div>

            }

        </div>
    )
}

export default UserComponent
JavaScript
//userSlice.js
import { createSlice } from "@reduxjs/toolkit";
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";

const initialState = {
    loading: false,
    users: [],
    error: "",
};

export const fetchUsers = createAsyncThunk("FETCH_USERS", async () => {
    return axios
        .get("https://jsonplaceholder.typicode.com/users")
        .then((response) => response.data.map((user) => user));
});

const userSlice = createSlice({
    name: "user",
    initialState,
    extraReducers: (builder) => {
        builder.addCase(fetchUsers.pending, (state) => {
            state.loading = true;
        });
        builder.addCase(fetchUsers.fulfilled, (state, action) => {
            state.loading = false;
            state.users = action.payload;
            state.error = "";
        });
        builder.addCase(fetchUsers.rejected, (state, action) => {
            state.loading = false;
            state.users = [];
            state.error = action.error.message;
        });
    },
});

export default userSlice.reducer;
JavaScript
//store.js
import { configureStore } from "@reduxjs/toolkit";
import userReducer from "../user/userSlice";

const store = configureStore({
    reducer: {
        user: userReducer,
    },
});

export default store;
JavaScript
//index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./store/store";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

To start the project

npm start

Output:

07

Final Output



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads