Open In App

Common middleware libraries used in Redux

Last Updated : 12 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Middleware libraries play a crucial role in Redux applications, enabling users to extend and enhance Redux’s capabilities. The middleware libraries offer a wide range of capabilities and cater to different use cases and preferences. users can choose the middleware that best fits their requirements and development style to enhance their Redux applications with additional features and functionality.

Some common middleware libraries used with Redux include:

  • Redux Thunk: Redux Thunk is one of the most popular middleware libraries for Redux. It allows users to write action creators that return functions instead of plain objects, enabling asynchronous logic such as API requests and side effects. Redux Thunk provides a straightforward approach to managing asynchronous operations in Redux applications.
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
  • Redux Saga: Redux Saga is a middleware library that leverages ES6 generators to handle asynchronous logic in Redux applications. It enables developers to write more complex asynchronous workflows, such as long-running tasks, concurrency control, and cancellation. Redux Saga provides a powerful and declarative approach to managing side effects in Redux.
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './reducers';
import rootSaga from './sagas';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
rootReducer,
applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(rootSaga);
  • Redux Observable: Redux Observable is a middleware library based on reactive programming principles and RxJS(Reactive Extensions for JavaScript). It allows users to handle asynchronous logic using observables, providing a powerful and composable way to manage complex async flows. Redux Observable is well-suited for applications with a heavy focus on event-driven programming and real-time data streams.
import { createStore, applyMiddleware } from 'redux';
import { createEpicMiddleware } from 'redux-observable';
import rootReducer from './reducers';
import rootEpic from './epics';
const epicMiddleware = createEpicMiddleware();
const store = createStore(
rootReducer,
applyMiddleware(epicMiddleware)
);
epicMiddleware.run(rootEpic);
  • Redux Promise Middleware: Redux Promise Middleware is a simple middleware that enables Redux to dispatch and handle promises as actions. It allows users to dispatch promises directly as Redux actions, simplifying the handling of asynchronous operations. Redux Promise Middleware is lightweight and easy to integrate into Redux applications.
import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise-middleware';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
applyMiddleware(promiseMiddleware)
);
export default store;
  • Redux Logger: Redux Logger is a middleware library that logs Redux actions and state changes to the console. It provides valuable insights into the flow of actions and the evolution of state within Redux applications, aiding in debugging and troubleshooting. Redux Logger is often used during development to track and monitor application behavior.
import { createStore, applyMiddleware } from 'redux';
import logger from 'redux-logger';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
applyMiddleware(logger)
);
  • Redux Batched Actions: Redux Batched Actions is a middleware library that batches multiple sequential actions into a single action, reducing unnecessary re-renders and improving performance. It is particularly useful for optimizing Redux applications with frequent state updates and rendering optimizations.
import { createStore, applyMiddleware } from 'redux';
import { enableBatching } from 'redux-batched-actions';
import rootReducer from './reducers';
const store = createStore(
enableBatching(rootReducer),
applyMiddleware(/* other middleware if needed */)
);
export default store;

Example: Below is the example of Redux middleware.

  • Install the necessary package in your application using the following command.
npm install redux-thunk react-redux redux-promise-middleware redux-logger

Javascript




// index.js
import React from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import App from "./App";
import store from "./store";
 
const root = createRoot(document.getElementById("root"));
 
root.render(
    <Provider store={store}>
        <App />
    </Provider>
);


Javascript




// App.js
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchData } from './actions/actions';
 
 
const App = () => {
    const dispatch = useDispatch();
    const { loading, data, error } = useSelector(state => state);
 
    useEffect(() => {
        dispatch(fetchData());
    }, [dispatch]);
 
    return (
        <div>
            {loading && <p>Loading...</p>}
            {data && (
                <div>
                    <h1>Data</h1>
                    <p>{JSON.stringify(data)}</p>
                </div>
            )}
            {error && <p>Error: {error}</p>}
        </div>
    );
};
 
export default App;


Javascript




// store.js
import { createStore, applyMiddleware } from 'redux';
// Correct import
import { thunk } from "redux-thunk"
import promiseMiddleware from 'redux-promise-middleware';
import { createLogger } from 'redux-logger';
import rootReducer from './reducers/reducer';
 
// Create logger middleware
const loggerMiddleware = createLogger();
 
// Apply middleware
const store = createStore(
    rootReducer,
    // correct use of thunk 
    applyMiddleware(thunk, promiseMiddleware, loggerMiddleware)
);
 
export default store;


Javascript




// actions.js
export const fetchData = () => {
    return async (dispatch) => {
        dispatch({ type: "FETCH_DATA_PENDING" });
        try {
            const response = await fetch("https://dummyjson.com/products");
            const data = await response.json();
            dispatch({ type: "FETCH_DATA_FULFILLED", payload: data });
        } catch (error) {
            dispatch({ type: "FETCH_DATA_REJECTED", payload: error.message });
        }
    };
};


Javascript




// reducers.js
const initialState = {
    loading: false,
    data: null,
    error: null,
};
 
const reducer = (state = initialState, action) => {
    switch (action.type) {
        case "FETCH_DATA_PENDING":
            return {
                ...state,
                loading: true,
                error: null,
            };
        case "FETCH_DATA_FULFILLED":
            return {
                ...state,
                loading: false,
                data: action.payload,
            };
        case "FETCH_DATA_REJECTED":
            return {
                ...state,
                loading: false,
                error: action.payload,
            };
        default:
            return state;
    }
};
 
export default reducer;


Start your application using the following command.

npm start

Output:

gfg17

Output



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

Similar Reads