Redux Logger: Logging State Changes in the Console

redux-logger is a middleware that prints every dispatched action and the resulting state change to the browser console. Configure it to collapse logs, filter by action type, and disable it in production.

June 28, 20263 min read3 / 4

The Redux DevTools extension shows state snapshots in a panel. Redux Logger does something different: it prints every action and state change directly to the browser console as it happens, in a readable group format.

It is built by LogRocket and installed as a standalone middleware.

Installation

Bash
npm install redux-logger

In src/store/index.js, import createLogger, create the logger instance, and add it as the last middleware in applyMiddleware:

JavaScript
import { createStore, applyMiddleware } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension'; import thunk from 'redux-thunk'; import { createLogger } from 'redux-logger'; import allReducers from '../reducers'; const logger = createLogger(); const store = createStore( allReducers, composeWithDevTools(applyMiddleware(thunk, logger)) ); export default store;

Logger must come last. If it runs before Redux Thunk, it cannot log thunk-dispatched actions correctly because Thunk has not yet resolved the functions into plain objects.

Every dispatched action now prints to the console with the previous state, the action object, and the next state.

Collapsing Logs by Default

By default all log groups are expanded. Pass a configuration object to createLogger:

JavaScript
const logger = createLogger({ collapsed: true });

All action groups collapse in the console. Click to expand any individual one.

To collapse only specific actions, pass a function instead of a boolean:

JavaScript
import * as actionTypes from '../constants/action-types'; const logger = createLogger({ collapsed: (getState, action) => action.type === actionTypes.FETCH_TASKS_REQUEST, });

The function receives getState, action, and logEntry. Return true to collapse, false to expand. This example keeps FETCH_TASKS_REQUEST collapsed but expands everything else.

Expanding Only on Errors

The logEntry parameter contains nextState and prevState. Use it to expand logs automatically when an error is present:

JavaScript
const logger = createLogger({ collapsed: (getState, action, logEntry) => !logEntry.nextState.tasks.error, });

When tasks.error is an empty string (no error), !'' is true, so the log collapses. When an error arrives, !errorMessage is false, so the log expands automatically. The error state is visible immediately without manually opening any group.

Disabling Logger in Production

Logger output should never reach end users in production. Control it with an environment variable.

Create a .env file at the root of the React app:

Plain text
REACT_APP_ENVIRONMENT=development

All Create React App environment variables must start with REACT_APP_. Restart npm start after any change to .env for the value to take effect.

In the store file, use the predicate configuration option:

JavaScript
const logger = createLogger({ collapsed: true, predicate: () => process.env.REACT_APP_ENVIRONMENT === 'development', });

predicate runs before every log. Return true to allow logging, false to suppress. When REACT_APP_ENVIRONMENT is development, logs appear. When it is production (or anything else), nothing is printed.

Before deploying to production, change the environment variable:

Plain text
REACT_APP_ENVIRONMENT=production

The build picks up the new value and the logger silences itself.

redux-logger middleware positioned at the end of the middleware chain Expandredux-logger middleware positioned at the end of the middleware chain

The Essentials

  1. Add logger last in applyMiddleware(thunk, logger). Middlewares before logger must run first or logger cannot see the resolved action.
  2. collapsed: true collapses all log groups. Pass a function to collapse selectively by action type or state shape.
  3. predicate controls whether any logging happens at all. Gate it on process.env.REACT_APP_ENVIRONMENT to disable logging in production without removing the package.

Further Reading and Watching