{"id":17907,"library":"redux-observable-middleware","title":"Redux Observable Middleware","description":"Redux Observable Middleware is a lightweight Redux middleware designed for integrating RxJS-like observables directly into Redux action creators. It is currently in an early stage of development, with the latest stable version being `0.2.0`, published 10 years ago. While there isn't a defined release cadence, its purpose is to simplify handling asynchronous data streams by automatically subscribing to any object with a `subscribe` method found within an action's `observable` property. This package dispatches specific lifecycle actions (`_ON_NEXT`, `_ON_ERROR`, `_ON_COMPLETED` or custom types) as the observable emits values, completes, or errors. This approach differs from more comprehensive solutions like `redux-observable`, which utilizes \"epics\" for side effects, offering a simpler, direct method for incorporating observables into the Redux data flow.","status":"abandoned","version":"0.2.0","language":"javascript","source_language":"en","source_url":"https://github.com/d6u/redux-observable-middleware","tags":["javascript"],"install":[{"cmd":"npm install redux-observable-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add redux-observable-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add redux-observable-middleware","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency for Redux middleware integration.","package":"redux","optional":false},{"reason":"Required for creating and handling observables, as demonstrated in examples with `Rx.Observable.interval`.","package":"rxjs","optional":false}],"imports":[{"note":"The original README examples use CommonJS `require`, but modern usage prefers ES Module `import` for tree-shaking and future compatibility.","wrong":"const observableMiddleware = require('redux-observable-middleware');","symbol":"observableMiddleware","correct":"import observableMiddleware from 'redux-observable-middleware';"},{"note":"While `createStore` can be destructured, the quickstart code uses `Redux.createStore`, implying a full namespace import or a global `Redux` object. Prefer named imports where possible in modern JS.","wrong":"import { createStore } from 'redux';","symbol":"Redux.createStore","correct":"import * as Redux from 'redux';"},{"note":"The original README uses `Rx.Observable`, implying a full namespace import. Modern RxJS encourages importing specific operators and `Observable` directly for better tree-shaking and clarity.","wrong":"import { Observable } from 'rxjs';","symbol":"Rx.Observable","correct":"import * as Rx from 'rxjs';"}],"quickstart":{"code":"import * as Redux from 'redux';\nimport * as Rx from 'rxjs';\nimport observableMiddleware from 'redux-observable-middleware';\n\nconst ACTION_TYPE = 'INTERVAL';\n\nfunction reducer(state = null, action) {\n  console.log('Action received:', action.type, action.data || action.err);\n  switch (action.type) {\n    case `${ACTION_TYPE}_ON_NEXT`:\n      return action.data;\n    case `${ACTION_TYPE}_ON_ERROR`:\n      console.error('Observable error:', action.err);\n      return state; // Or handle error appropriately\n    case `${ACTION_TYPE}_ON_COMPLETED`:\n      console.log('Observable completed.');\n      return state;\n    default:\n      return state;\n  }\n}\n\nconst store = Redux.createStore(reducer, Redux.applyMiddleware(observableMiddleware));\n\nstore.subscribe(() => {\n  console.log('Current state:', store.getState());\n});\n\nconsole.log('Dispatching observable action...');\nstore.dispatch({\n  type: ACTION_TYPE,\n  observable: Rx.interval(1000).pipe(Rx.take(5))\n});","lang":"javascript","description":"This quickstart demonstrates how to integrate an RxJS observable into a Redux action using `redux-observable-middleware`. It sets up a basic Redux store with the middleware, dispatches an action containing an observable that emits values every second, and logs the state changes as the observable progresses through its `ON_NEXT`, `ON_ERROR`, and `ON_COMPLETED` lifecycle actions."},"warnings":[{"fix":"Consider migrating to `redux-observable` (the actively maintained alternative) or extensively testing compatibility with a modern RxJS setup, adapting observable creation and operator chaining.","message":"The package `redux-observable-middleware` has not been updated in a very long time (last publish 10 years ago for v0.2.0) and uses an older style of RxJS (implied RxJS 4/5 by the `Rx.Observable.interval` syntax). Modern RxJS (v6+) uses pipeable operators (`.pipe(operator())`) and has different import paths and usage patterns. Compatibility with newer RxJS versions is not guaranteed and requires careful adaptation.","severity":"gotcha","affected_versions":">=0.2.0"},{"fix":"Review any existing logic that specifically depends on the timing or presence of the `onSubscribe` action relative to other lifecycle actions for an observable. Ensure your state updates or side effects correctly account for the `onSubscribe` action always being the first dispatched.","message":"The behavior of `onSubscribe` actions was refined in v0.2.0 to ensure they are always dispatched first, regardless of the observable type. While intended as a fix, this is a behavioral change that might affect logic relying on the previous, less consistent dispatch order for `onSubscribe` actions.","severity":"breaking","affected_versions":">=0.2.0"},{"fix":"Always include `catchError` operators within your RxJS observable chains to handle errors gracefully before they propagate out of the observable. Dispatch an appropriate action within `catchError` to inform the Redux store of the error, as shown in `redux-observable` patterns. For example: `observable.pipe(map(data => ({ type: 'ON_NEXT', data })), catchError(err => of({ type: 'ON_ERROR', err })))`.","message":"Error handling within the observable is crucial. If an observable errors out and is not caught, it can lead to uncaught exceptions or the observable stream terminating prematurely, preventing further actions from being processed for that specific observable. The middleware itself provides an `_ON_ERROR` action, but the observable stream itself needs internal `catchError` operators for resilience.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure that the `observable` property in your Redux action is an instance of an RxJS Observable or any object that implements a `subscribe` method. Double-check that `rxjs` is correctly imported and `Observable` instances are created correctly.","cause":"The `observable` property in your dispatched action is not a valid Observable-like object (i.e., it does not have a `subscribe` method). This could be due to forgetting to include the `observable` property, passing `undefined`, or passing a non-observable object.","error":"TypeError: observable.subscribe is not a function"},{"fix":"If using a string `type`, ensure your reducer handles both the original `ACTION_TYPE` and its suffixed variants (e.g., `ACTION_TYPE_ON_NEXT`). If using an object `type`, be explicit about which lifecycle actions you want to dispatch by defining `onSubscribe`, `onNext`, `onError`, `onCompleted` properties in the `type` object of your action.","cause":"When using a string for the `type` property (e.g., `'MY_ACTION_TYPE'`), the middleware dispatches the original action type immediately (`ACTION_A`), then suffixes for `ON_NEXT`, `ON_ERROR`, `ON_COMPLETED`. If you are only listening for `ON_NEXT` etc., you might miss the initial action. If `type` is an object, only specified keys like `onNext` will dispatch.","error":"Actions with type `MY_ACTION_TYPE` are not handled, but `MY_ACTION_TYPE_ON_NEXT` is."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}