DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • How to Build Scalable Mobile Apps With React Native: A Step-by-Step Guide
  • Mastering React App Configuration With Webpack
  • Overcoming React Development Hurdles: A Guide for Developers

Trending

  • Customer 360: Fraud Detection in Fintech With PySpark and ML
  • Unlocking the Benefits of a Private API in AWS API Gateway
  • Understanding and Mitigating IP Spoofing Attacks
  • MySQL to PostgreSQL Database Migration: A Practical Case Study
  1. DZone
  2. Coding
  3. JavaScript
  4. React Middleware: Bridging APIs and Components

React Middleware: Bridging APIs and Components

React-based UI is adopting middleware as a way to handle complex asynch functionalities during state management to manage application flow effectively.

By 
Anant Wairagade user avatar
Anant Wairagade
·
Feb. 13, 25 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
5.9K Views

Join the DZone community and get the full member experience.

Join For Free

Middleware is not a new concept in web development. It is typically associated with backend frameworks like Express.js, where there is a lot of authentication, logging, etc. Because of its inherent advantages, middleware has gained significant traction in the frontend.

Frontend frameworks such as React are adopting it as a way to handle complex functionalities during state management. In this guide, we’ll walk you through the concept of middleware in React and how to use it to enhance your React app’s functionality and manage application flow effectively.

By the end of it, you’ll have a good grasp of what React middleware is and how to implement it with Redux Thunk.

React Middleware Simplified: Streamlining Application Logic

What Is Middleware?

As the name suggests, middleware is a layer that sits between different components of an application. It provides a layer of processing and functionality here when there wouldn’t be one without it. Middleware works by intercepting requests flowing from one component to another and allows you to perform specific actions. Once done it passes the modified request to the next middleware or its intended destination.

This is a concept primarily used in the backend. But, as mentioned earlier, it has been adapted in React to serve a similar purpose. Now, let’s dive into what middleware means, specifically in React.

Middleware in React

In React, middleware is implemented as a series of functions, executed one after the other, in the order you define them. Each function has access to the app’s state and actions. Hence, the functions can modify and dispatch new actions.

When state changes in React, the application dispatches actions which are then handled by the Reducer(s). The Reducer(s) will then return a new state, which is then stored and passed back to the application.

Data flow

React middleware sits between the dispatched action and intercepts it before it reaches the reducer. Then, it allows you to hook into this process and execute some code on this action, for example, logging it or making an API call.

Once this is done, it will pass the modified action to the Reducer (if there isn’t another middleware in the chain).

Examples of Middleware in React

You can find React middleware mainly in Redux, the complex state management React library. Redux has two main types of middleware:

  • Thunk – we’ll dive deeper into how to use this middleware to modify an action.
  • Saga.

Each of them handles different types of modifications to actions, as we’ll see below when looking at the uses of middleware in React. Other React libraries, such as React Query, also use middleware (more on this later).

Before we look at how to implement this, let’s go over the different uses of middleware in React.

Uses of Middleware in React

React middleware comes in handy for the following use cases:

Debugging and Logging

React middleware can be used to log information like current state, actions, and other data during the application development. Moreover, these can be useful for identifying the potential bugs and errors for early resolution.

The Redux Logger (for Redux) can help you do this. It logs Redux actions and state changes for easy debugging. It intercepts every dispatched action and logs the previous state, action, and the next state.

Authorization and Authentication

If you want to authenticate users before you update state you can use Redux Thunk or Saga to handle the authentication workflows. Once you intercept an action this middleware enables you to store tokens, check authentication before dispatching the action, or refresh tokens.

In other words, these middleware are useful for checking whether a user is authenticated to access a particular route or not.

Event-Driven Operations

The React reducer is designed to run synchronous code. This means that if you attempt to run anything asynchronous on it, it won’t work. With React middleware such as Redux Thunk, you can catch the action, perform async tasks like making an API call, and proceed to the reducer once this is done.

Caching Data

React Query (another React middleware) can serve as an effective tool in caching application data. It caches API responses automatically and revalidates them when needed. As a result, it helps you avoid redundant API calls by checking for the required information in the cache.

Performance Enhancement

React middleware can also help enhance the application's performance by delaying unnecessary actions for later, debouncing events, and batch-processing certain tasks. By caching API responses, React Query also enhances the performance of your React apps.

How to Use Middleware in React?

Redux is a powerful tool for managing global state in React applications. It includes several middleware in its toolkit you can use to add custom functionality to your React apps. One of the most common ones is Redux Thunk.

Introduction to Redux Thunk

Before diving deep into the implementation of Thunk, let's gather some information about it so that we can use it effectively.

What Is Thunk?

In general programming, a “Thunk” is simply a function that is used to delay the evaluation and execution of a function. We can look at it as a function that postpones an action until a specific condition is met.

In Redux, a thunk is a specific function used with the Redux Thunk middleware. Redux Thunk is designed to allow asynchronous operations within your React app. Earlier on we mentioned that the Reducer is built to run synchronous code. This means when an action is dispatched, the reducer updates state immediately.

Redux Thunk as Middleware

Redux Thunk acts as middleware. It allows you to write action creators that return functions (thunks) instead of plain action objects. These functions can contain asynchronous logic. When you dispatch a thunk, the Thunk middleware intercepts it and executes the function.

Inside the thunk, you can perform your asynchronous operation (e.g., make an API call) and then dispatch regular actions to update the Redux store when the operation is complete.

Note: Redux Thunk allows both asynchronous and synchronous operations, although its primary purpose is to facilitate asynchronous actions. It doesn't prevent you from dispatching synchronous actions; it simply provides a mechanism for handling asynchronous ones as well.

With that out of the way, let’s see React middleware in action by implementing Redux Thunk.

A Step-by-Step Guide to Implementing Redux Thunk

Implementing Redux middleware involves the following steps:

Step 1: Set Up Redux With Thunk

Create a React application and install the dependencies.

Plain Text
 
npx create-react-app newApp


Step 2: Install Redux Thunk

Run the following command to install Redux Thunk.

Plain Text
 
npm install redux-thunk


Step 3: Enable Thunk Middleware

JavaScript
 
Enable the Thunk middleware in the Redux store.

import { configureStore } from '@reduxjs/toolkit';
import thunk from 'redux-thunk';
import rootReducer from './reducers'; // Combine all reducers here

const store = configureStore({
reducer: rootReducer,
middleware: [thunk],
});

export default store;


Note: When using Redux Toolkit, there is no need to install thunk explicitly.

Step 4: Writing Async Function

A thunk returns another function that receives the dispatch and getstate arguments to read the state or dispatch actions. The following is the example code for fetching data:

JavaScript
 
// Action types
const START_FETCH = 'START_FETCH';
const FETCH_SUCCESS = 'FETCH_SUCCESS';
const FETCH_ERROR = 'FETCH_ERROR';

  // Action creators
const startFetch = () => ({ type: START_FETCH });
const fetchSuccess = (data) => ({ type: FETCH_SUCCESS, payload: data });
const fetchError = (error) => ({ type: FETCH_ERROR, payload: error });

  // Thunk action
export const fetchData = () => {
return async (dispatch, getState) => {
      dispatch(startFetch()); // Notify that the fetch has started

try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error('Failed to fetch data');
}
const data = await response.json();

        dispatch(fetchSuccess(data)); // Send the fetched data to the store
} catch (error) {
         dispatch(fetchError(error.message)); // Handle any errors
}
};
  };


Step 5: Handling Dispatched Actions in Reducer

Handle the dispatched actions by updating the reducer.

JavaScript
 
const initialState = {
data: [],
    isLoading: false,
    error: null,
};

export const dataReducer = (state = initialState, action) => {
switch (action.type) {
case START_FETCH:
return { ...state, isLoading: true, error: null };
case FETCH_SUCCESS:
return { ...state, isLoading: false, data: action.payload };
case FETCH_ERROR:
return { ...state, isLoading: false, error: action.payload };
default:
return state;
}
  };


Step 6: Dispatching Thunk From a Component

Use the useDispatch hook to dispatch thunks in React projects.

JavaScript
 
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchData } from './actions';

const DataComponent = () => {
const dispatch = useDispatch();
const { data, isLoading, error } = useSelector((state) => state.data);

useEffect(() => {
      dispatch(fetchData()); // Trigger the thunk to fetch data
}, [dispatch]);

if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;

return (
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
};

export default DataComponent;


Using createAsyncThunk

The Redux Toolkit contains a built-in API that defines high-level logic for async functions, dispatches them, and handles errors promptly. Please note that as this provides an abstraction for the specific use cases of async functions, createAsyncThunk does not apply to all the use cases of thunks. 

The following is the example implementation of the createAsyncThunk:

JavaScript
 
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

export const dataFetch = createAsyncThunk('data/fetchData', async () => {
const response = await fetch('https://api.example.com/data');
return response.json();
});

const dataSlice = createSlice({
    name: 'data',
    initial_State: { data: [], loading: false, error: null },
extraReducers: (builder) => {
builder
.addCase(dataFetch.pending, (state) => {
          state.loading = true;
          state.error = null;
})
.addCase(dataFetch.fulfilled, (state, action) => {
          state.loading = false;
state.data = action.payload;
})
.addCase(dataFetch.rejected, (state, action) => {
          state.loading = false;
state.error = action.error.message;
});
},
});

export default dataSlice.reducer;


Now, to dispatch the dataFetch thunk, use the following code:

JavaScript
 
dispatch(dataFetch ());


Uses of React Middleware – Redux Thunk

Thunks can be used for a variety of purposes, including but not limited to:

  • Abstracting complex logic from the components. 
  • Making async requests and logic. 
  • Write functions to dispatch multiple actions in a series. 

React Middleware in Other State Management Libraries

Redux isn’t the only React library that leverages middleware. You can also find them in other state management libraries, although the implementation of this concept in these libraries is different from how it is done in Redux.

MobX

MobX doesn’t have traditional middleware like Redux. It offers similar functionality through mechanisms such as interceptors, observers, and reactions. These mechanisms allow you to observe changes in your MobX state and react to them. In this way, MobX provides ways to handle side effects, logging, and other tasks middleware typically handles in Redux.

Recoil

Recoil doesn’t support middleware in the same way as Redux because it doesn’t need to. It allows you to directly update pieces of state (atoms) using specific functions. There is no dispatching of actions to a reducer, which you can intercept with middleware. To handle async operations, it uses selectors — derived state depending on atoms or other selectors.

Zustand

It helps manage states with a simple API and supports native middleware for logging and storing states, just like Redux.

XState

XState supports middleware-like behavior using hooks such as onTransition, actions, and services. These hooks help to intercept and modify state transitions.

Conclusion

Middleware acts as a bridge to connect and combine different components of a web application for better data flow and handling. They have been widely used on the backend ever since, but now have found use cases on the frontend as well.

In React, there are various ways to implement the middleware. They are usually linked to the state management libraries such as Redux, and MobX. The most commonly used React middleware, Thunk, is included in the Redux library. A thunk is a code block that performs the delayed tasks.

In this article, we have explored Middleware in React, Redux library, and Redux Thunk. We also covered steps to implement Redux Thunk middleware for fetching data and dispatching actions.

Middleware React (JavaScript library) JavaScript

Opinions expressed by DZone contributors are their own.

Related

  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • How to Build Scalable Mobile Apps With React Native: A Step-by-Step Guide
  • Mastering React App Configuration With Webpack
  • Overcoming React Development Hurdles: A Guide for Developers

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!