# How the Redux Observable Method Supports Reactive Library Integration

> Learn how Redux observable integrates reactive libraries like RxJS by treating the store as a stream of state changes. Discover the power of the subscribe interface.

- Repository: [Redux/redux](https://github.com/reduxjs/redux)
- Tags: deep-dive
- Published: 2026-03-05

---

**Redux’s `observable` method implements the TC39 Observable proposal, exposing a minimal `subscribe` interface that allows reactive libraries like RxJS to treat the store as a stream of state changes.**

The `observable` method in the [reduxjs/redux](https://github.com/reduxjs/redux) repository provides a standards-compliant bridge between Redux’s imperative store and reactive programming paradigms. By implementing the TC39 Observable proposal, this method enables seamless integration with libraries like RxJS, most.js, and zen-observable without requiring additional adapters.

## What Is the Redux Observable Method?

The observable method is a minimal Observable implementation attached to every Redux store. It follows the [TC39 Observable proposal](https://github.com/tc39/proposal-observable) specification, providing a `subscribe` method that emits the current state immediately upon subscription and then forwards all future state changes.

Unlike full-featured reactive libraries, Redux’s implementation is intentionally lightweight. It resides in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts) and provides only the essential Observable contract: a `subscribe` method and a self-referencing `[Symbol.observable]()` method.

## How the Observable Method Works Under the Hood

### The observable() Factory in src/createStore.ts

The implementation lives inside the `createStore` function in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts). The `observable()` function constructs and returns the Observable object:

```typescript
// src/createStore.ts
function observable() {
  const outerSubscribe = subscribe
  return {
    subscribe(observer: unknown) {
      if (typeof observer !== 'object' || observer === null) {
        throw new TypeError('Expected the observer to be an object.')
      }

      function observeState() {
        const observerAsObserver = observer as Observer<S>
        if (observerAsObserver.next) {
          observerAsObserver.next(getState())
        }
      }

      observeState()
      const unsubscribe = outerSubscribe(observeState)
      return { unsubscribe }
    },

    [$$observable]() {
      return this
    }
  }
}

```

The function captures the store’s native `subscribe` function as `outerSubscribe`, allowing the Observable to tap into Redux’s existing subscription mechanism.

### Subscription Protocol and Immediate Emission

The observable method follows a specific emission pattern:

1. **Immediate state emission** – Upon subscription, `observeState()` is called immediately, pushing the current store state to the observer via `observer.next(getState())`.
2. **Future update forwarding** – The `outerSubscribe(observeState)` call registers the observer to receive all subsequent state changes through Redux’s native subscription system.
3. **Unsubscription** – The returned object contains an `unsubscribe` method that delegates to the store’s unsubscribe function.

This behavior ensures that reactive libraries receive the current state as a "cold" emission followed by "hot" updates, matching the expected Observable contract.

### Symbol.observable Interoperability

The observable method implements the required `[Symbol.observable]()` method (aliased as `$$observable` in the source):

```typescript
[$$observable]() {
  return this
}

```

This self-referencing method satisfies the TC39 specification requirement that `observable[Symbol.observable]()` must return the same observable instance.

The symbol itself is resolved in [`src/utils/symbol-observable.ts`](https://github.com/reduxjs/redux/blob/main/src/utils/symbol-observable.ts), which provides a fallback to the string `'@@observable'` when the native `Symbol.observable` is unavailable:

```typescript
// src/utils/symbol-observable.ts
export default (() =>
  (typeof Symbol === 'function' && Symbol.observable) || '@@observable')()

```

## TypeScript Types and Store Integration

The type definitions in [`src/types/store.ts`](https://github.com/reduxjs/redux/blob/main/src/types/store.ts) formally declare the Observable contract:

```typescript
// src/types/store.ts
export type Observable<T> = {
  subscribe: (observer: Observer<T>) => { unsubscribe: Unsubscribe }
  [Symbol.observable](): Observable<T>
}

```

The store object itself is constructed with the observable method attached to the `$$observable` symbol:

```typescript
// src/createStore.ts
const store = {
  dispatch,
  subscribe,
  getState,
  replaceReducer,
  [$$observable]: observable
} as Store & Ext

```

This allows reactive libraries to access the observable via `store[Symbol.observable]()` or simply `store[Symbol.observable]` depending on their consumption pattern.

## Integrating Redux with RxJS and Other Reactive Libraries

### Converting the Store to an RxJS Observable

Because Redux implements the Observable spec, RxJS can treat the store as a first-class Observable source using the `from` creation operator:

```typescript
import { from } from 'rxjs'
import { filter, map } from 'rxjs/operators'
import { createStore } from 'redux'

const store = createStore(counterReducer)

// RxJS recognizes store[Symbol.observable]()
const state$ = from(store)

// Apply RxJS operators
state$
  .pipe(
    filter(state => state.count > 0),
    map(state => state.count)
  )
  .subscribe(count => console.log('Positive count:', count))

```

The `from` operator automatically detects the `Symbol.observable` property and uses the `subscribe` method to bridge Redux state changes into the RxJS stream.

### Using most.js and Other TC39-Compliant Libraries

Other reactive libraries that support the TC39 proposal can consume the Redux store directly:

```typescript
import most from 'most'
import { createStore } from 'redux'

const store = createStore(reducer)

// most.js checks for Symbol.observable
const stateStream = most.from(store)

stateStream.observe(state => {
  console.log('State update via most.js:', state)
})

```

The same pattern works with `zen-observable` and other spec-compliant implementations, demonstrating the universal interoperability provided by the observable method.

## Summary

- **TC39 Compliance**: The observable method implements the TC39 Observable proposal, providing a `subscribe` method and `[Symbol.observable]()` self-reference.
- **Location**: The implementation resides in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts), with type definitions in [`src/types/store.ts`](https://github.com/reduxjs/redux/blob/main/src/types/store.ts) and symbol polyfill in [`src/utils/symbol-observable.ts`](https://github.com/reduxjs/redux/blob/main/src/utils/symbol-observable.ts).
- **Emission Pattern**: The observable immediately emits the current state upon subscription, then forwards all future state changes through Redux's native subscription system.
- **Interop**: Reactive libraries like RxJS, most.js, and zen-observable can consume the store directly using `from(store)` or equivalent operators that detect `Symbol.observable`.

## Frequently Asked Questions

### What is the TC39 Observable proposal?

The TC39 Observable proposal is a standardization effort to add native Observable support to JavaScript. It defines a minimal interface where an object must provide a `subscribe` method that accepts an observer (with `next`, `error`, and `complete` methods) and return a subscription object with an `unsubscribe` method. The proposal also requires a `[Symbol.observable]()` method that returns the observable itself, enabling recursive unwrapping by reactive libraries.

### How does Redux's observable method differ from RxJS?

Redux's observable method is a **minimal** implementation that only supports the core TC39 contract, whereas RxJS provides a full-featured reactive programming library with hundreds of operators and advanced scheduling capabilities. The Redux implementation specifically emits the current state immediately upon subscription and then forwards future state changes, but it does not include operators like `map`, `filter`, or `debounce`. RxJS can wrap Redux's minimal observable using `from(store)` to add these capabilities.

### Can I use the observable method without installing RxJS?

Yes, the observable method works independently of RxJS or any other reactive library. You can access it directly via `store[Symbol.observable]()` and subscribe using the native `subscribe` method with a plain observer object:

```typescript
const observable = store[Symbol.observable]()
const subscription = observable.subscribe({
  next: (state) => console.log(state)
})

```

This approach requires no external dependencies beyond Redux itself, though you must implement your own stream processing logic since the native observable provides only basic subscription capabilities.

### Why does the observable emit the current state immediately?

The immediate emission of the current state upon subscription follows the **"cold then hot"** pattern common in reactive programming. When a subscriber connects to the Redux store, it receives the current state as an initial value (the "cold" emission), ensuring the observer has immediate access to the data without waiting for the next dispatch. Subsequent emissions occur whenever the state changes (the "hot" updates), forwarded through Redux's native subscription system. This behavior ensures consistency with the TC39 proposal and matches the expectations of reactive libraries that assume observables emit initial values upon subscription.