"composeEnhancers" is not a function in ReactJS

You are likely running your app in dev mode in a browser that doesn't have Redux DevTools installed.

The problem is in this line:

const composeEnhancers = process.env.NODE_ENV === 'development' ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : null || compose;

Due to operator precedence rules, this is equivalent to:

const composeEnhancers = process.env.NODE_ENV === 'development' ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : (null || compose);

Or if you prefer:

let composeEnhancers = null;
if (process.env.NODE_ENV === 'development') {
    composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
} else {
    composeEnhancers = compose;
}

So, if you are in dev mode and you don't have Redux DevTools extension installed in your browser, your app will break, because window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ is not defined. What you really need is this:

let composeEnhancers = null;
if (process.env.NODE_ENV === 'development') {
    composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
} else {
    composeEnhancers = compose;
}

Or, more simply:

const composeEnhancers = (process.env.NODE_ENV === 'development' ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : null) || compose;

2020 update


With Elvis (or safe navigation) operator that was introduced in TypeScript 3.8 it's possible to simplify it and make it look much better. Like below:

const composeEnhancers =
  (process.env.NODE_ENV === 'development' &&
    (window as any)?.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
  compose;

What it means is:

  • elvis operator checks if window?.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ is defined
  • if it not exist it evaluates to undefined so first part of code returns false (if we are in development mode -> true && undefined = false) and fallback evaluates

Tags:

Node.Js

Npm