Middleware plays a powerful role in Redux applications — it allows us to run custom logic between when an action is dispatched and when it reaches the reducer.
In this article, we’ll learn how to create a logging middleware to track actions and state changes. This is extremely helpful for debugging, monitoring user behavior, or understanding state flow in the app.
Middleware is a function that sits between:
Component → dispatch(action) → Middleware → Reducer → Updated State
This means we can:
Redux Toolkit already includes some middleware, like:
redux-thunk (for async actions)immutable & serializable state checks (for development)But we can still add custom middleware.
Let’s create a middleware that logs:
Create a file:
src/middleware/logger.js
export const logger = (store) => (next) => (action) => {console.log("%cAction Dispatched:", "color: #4CAF50; font-weight: bold;", action);console.log("%cPrevious State:", "color: #FF5722;", store.getState());const result = next(action); // let reducer runconsole.log("%cUpdated State:", "color: #2196F3;", store.getState());console.log("---------------------------------------------------");return result;};
| Part | Meaning |
|---|---|
store.getState() | Reads current global state |
next(action) | Passes action to reducer |
| Logs before + after | Helps visually track state updates |
Open your store file:
src/store.js
import { configureStore } from "@reduxjs/toolkit";import { logger } from "./middleware/logger";import counterReducer from "./features/counter/counterSlice";export const store = configureStore({reducer: {counter: counterReducer,},middleware: (getDefaultMiddleware) =>getDefaultMiddleware().concat(logger),});
.concat()?getDefaultMiddleware() returns the built-in RTK middleware.concat(logger) adds our custom middleware to the chainNow, whenever you trigger a Redux action, your console will display:
Action Dispatched: incrementPrevious State: { counter: { value: 5 } }Updated State: { counter: { value: 6 } }---------------------------------------------------
This makes it easy to:
✅ During development ✅ When debugging complex applications ✅ When learning Redux ✅ When reviewing reducer behavior
❌ Do not use it in production unless you truly need it It may reveal sensitive data or slow down performance.
| Concept | Explanation |
|---|---|
| Middleware | Code that runs between dispatch and reducers |
| Logger Middleware | Helps observe state updates step-by-step |
Added via middleware config in RTK store | Works alongside default middleware |
Middleware is one of the most powerful features of Redux. It gives you control, visibility, and flexibility.