Redux Logic Middleware

raw JSON →
5.0.2 verified Thu Apr 23 auth: no javascript

Redux Logic is a middleware for Redux applications designed to centralize and organize business logic and side effects. It allows developers to intercept actions and perform asynchronous processing, supporting various JavaScript styles including callbacks, Promises, async/await, and Observables (via RxJS). The current stable version is 5.0.2. Release cadence typically involves minor and patch versions for dependency updates and security fixes, with major versions reserved for significant changes like dropping Node.js version support or altering internal event structures. Key differentiators include its declarative API for common side effect patterns (filtering, cancellation, latest request handling, debouncing, throttling), robust testing support via `redux-logic-test`, simplified server-side rendering, and the ability to dynamically load logic for code-splitting scenarios. It aims to provide a flexible alternative to libraries like Redux Saga and Redux Observable by allowing developers to choose their preferred async programming paradigm within a declarative framework.

error Error: Cannot find module 'redux'
cause `redux` is a peer dependency of `redux-logic` and must be installed separately.
fix
Install redux in your project: npm install redux or yarn add redux.
error TypeError: (0 , redux_logic_1.createLogic) is not a function
cause This error often occurs when trying to `require` an ESM-style export in a CommonJS module, or when a bundler misinterprets the module's export format, or when using an incorrect named import in TypeScript.
fix
Ensure you are using correct import syntax for your module type (e.g., import { createLogic } from 'redux-logic'; for ESM, or const { createLogic } = require('redux-logic'); for CJS) and that your bundler/TypeScript configuration is set up correctly for module resolution.
error TypeError: middleware is not a function (when applying middleware)
cause The `createLogicMiddleware` function needs to be *called* with an array of logics to return the actual middleware function. If you pass `createLogicMiddleware` itself instead of its return value to `applyMiddleware`, this error will occur.
fix
Ensure you call createLogicMiddleware with your logic array, like applyMiddleware(createLogicMiddleware([myLogic])), rather than applyMiddleware(createLogicMiddleware).
error TypeError: Cannot read properties of undefined (reading 'message') in monitor$ handler
cause Since v4.0.0, the `err` object passed to `monitor$` is now the raw `Error` object, not just a string. If your handler expects `err` to be a string and directly accesses `err.message` without checking, this could happen if `err` is not an object or null.
fix
Update your monitor$ handler to properly check if err is an Error object before accessing its properties, e.g., error.message or error.stack.
breaking The `monitor$` notification event handler now signals with the raw error object (`err`) instead of just the error message (`err.message`) if an error was thrown. Code expecting a string should be updated to handle an `Error` object.
fix Update `monitor$` handlers to access `err` as an object, e.g., `err.message` for the string, or other properties of the error object.
breaking Node.js v6 support was dropped in `redux-logic` v3.0.0 due to dependency upgrades. Applications running on Node.js v6 or older will encounter compatibility issues.
fix Upgrade your Node.js runtime to version 8.0.0 or higher. The package.json `engines` field specifies `>=8.0.0`.
gotcha The UMD build of `redux-logic` is no longer ES5 compatible as of v5.0.0; it now targets ES6. If you are using the UMD build directly in browsers that only support ES5, it will likely break.
fix Ensure that your build pipeline transpiles `redux-logic` (or its UMD output) to ES5 if you need to support older browsers without native ES6 capabilities. For modern browsers or bundler usage, this is generally not an issue.
gotcha A 'slight reduction in the number of logics that can be loaded' was noted in v5.0.0 due to updates in the RxJS library. While not an API change, extremely large applications might theoretically hit new internal limits.
fix This is unlikely to affect most applications. For exceptionally large applications, monitor memory usage and consider refactoring or splitting logic bundles if issues arise.
npm install redux-logic
yarn add redux-logic
pnpm add redux-logic

This quickstart demonstrates how to define and integrate a `redux-logic` unit that fetches data, handles success/failure, and supports cancellation and 'take latest' behavior within a Redux store.

import { createStore, applyMiddleware } from 'redux';
import { createLogic, createLogicMiddleware } from 'redux-logic';
import axios from 'axios'; // Example dependency, install if needed: npm install axios

const FETCH_POLLS = 'FETCH_POLLS';
const FETCH_POLLS_SUCCESS = 'FETCH_POLLS_SUCCESS';
const FETCH_POLLS_FAILED = 'FETCH_POLLS_FAILED';
const CANCEL_FETCH_POLLS = 'CANCEL_FETCH_POLLS';

// Reducer
const initialState = { polls: [], loading: false, error: null };
function reducer(state = initialState, action) {
  switch (action.type) {
    case FETCH_POLLS: return { ...state, loading: true, error: null };
    case FETCH_POLLS_SUCCESS: return { ...state, loading: false, polls: action.payload };
    case FETCH_POLLS_FAILED: return { ...state, loading: false, error: action.payload };
    default: return state;
  }
}

// Logic definition
const fetchPollsLogic = createLogic({
  type: FETCH_POLLS,
  cancelType: CANCEL_FETCH_POLLS,
  latest: true,

  process({ getState, action }, dispatch, done) {
    axios
      .get('https://survey.codewinds.com/polls')
      .then((resp) => resp.data.polls)
      .then((polls) => dispatch({ type: FETCH_POLLS_SUCCESS, payload: polls }))
      .catch((err) => {
        console.error('Fetch polls error:', err); // Log error
        dispatch({ type: FETCH_POLLS_FAILED, payload: err.message, error: true });
      })
      .then(() => done()); // Always call done when finished
  }
});

// Configure middleware and store
const logicMiddleware = createLogicMiddleware([fetchPollsLogic]);
const store = createStore(reducer, applyMiddleware(logicMiddleware));

// Dispatch an action to trigger the logic
console.log('Dispatching FETCH_POLLS action...');
store.dispatch({ type: FETCH_POLLS });

// Optional: Simulate cancellation after a delay
// setTimeout(() => {
//   console.log('Dispatching CANCEL_FETCH_POLLS action...');
//   store.dispatch({ type: CANCEL_FETCH_POLLS });
// }, 100);

// Listen for state changes (for demonstration)
const unsubscribe = store.subscribe(() => {
  console.log('Current state:', store.getState());
  if (!store.getState().loading) {
    unsubscribe(); // Stop listening once loading is complete
  }
});