Giter VIP home page Giter VIP logo

redux-observable's Introduction

redux-observable (beta) Build Status npm version

RxJS 5-based middleware for Redux. Compose and cancel async actions and more.

  • Dispatch a function that returns an observable of actions, a promise of action or iterable of actions.
  • Function is provided a stream of all future actions, useful for composition with the current dispatched observable, especially for cancellation. (think things like takeUntil or zip)
  • Function is also provided a reference to the store which can be used to get the state or even dispatch.

Read about it on Medium

Install

NOTE: This has a peer dependencies of [email protected].* and redux, which will have to be installed as well.

npm install --save redux-observable

Usage

Basic

Add the middlware to your redux store:

import { createStore, applyMiddleware } from 'redux';
import { reduxObservable } from 'redux-observable';

const store = createStore(
  rootReducer,
  // Notice that we invoke `reduxObservable()` before passing it!
  applyMiddleware(reduxObservable())
);

With redux-observable, you can dispatch any function that returns an observable, a promise, an observable-like object or an iterable; we call this a "thunkservable".

Your thunkservable emits a stream of actions.

Here are several examples:

// using RxJS
dispatch(() => Rx.Observable.of({ type: 'ASYNC_ACTION_FROM_RX' }).delay(1000));
// using a Promise
dispatch(() => Promise.resolve({ type: 'ASYNC_ACTION_FROM_PROMISE'}));
// using an Array of actions
dispatch(() => [{ type: 'ACTION_1' }, { type: 'ACTION_2' }]);
// using a generator of actions
dispatch(() => (function* () {
  for (let i = 0; i < 10; i++) {
    yield { type: 'SOME_GENERATED_ACTION', value: i };
  }
}()));

Of course, you'll usually create action factories instead:

const asyncAction = () => (
  (actions, store) => Rx.Observable.of({ type: 'ASYNC_ACTION_FROM_RX' }).delay(1000)
);

dispatch(asyncAction());

const fetchUserById = (userId) => (
  (actions) => (
    Rx.Observable.ajax(`/api/users/${userId}`)
      .map(
        (payload) => ({ type: 'FETCH_USER_FULFILLED', payload })
      )
      .startWith({ type: 'FETCH_USER_PENDING' })
  )
);

dispatch(fetchUserById(123));

// If you find it more readable, you certainly can omit all those
// arrow function parenthesis (or use regular functions)

const fetchUserById = userId =>
  actions =>
    Rx.Observable.ajax(`/api/users/${userId}`)
      .map(payload => ({ type: 'FETCH_USER_FULFILLED', payload }))
      .startWith({ type: 'FETCH_USER_PENDING' });

Cancellation

It's recommended to dispatch an action to cancel your async action with Rx. This can be done by leveraging the first argument to your dispatched function, which returns an observable of all actions. This observable is an instanceof ActionObservable and has a custom operator ofType. The ofType operator can be used to filter down to a set of actions of a particular type. It is essentially an alias for filter(action.type === 'SOME_TYPE'). You can use this stream of all actions with operators like takeUntil to abort the async action cleanly and via composition.

dispatch(
  (actions) => Observable.timer(1000)
    .map(() => ({ type: 'TIMER_COMPLETE'}))
    .takeUntil(
      actions.ofType('ABORT_TIMER')
    )
    // `actions.ofType('ABORT_TIMER')` is equivalent to
    // `actions.filter(action => action.type === 'ABORT_TIMER')`
);

// elsewhere in your code you can abort with a simple dispatch
dispatch({ type: 'ABORT_TIMER' });

You can also cancel an async dispatch by using the return value from your dispatch, which is an Rx Subscription. This works well for other types that don't have cancellation, like promises, but internally will really use "disinterest" to stop the resolved value from propagating.

let subscription = dispatch(() => Promise.resolve({ type: 'DELAYED_ACTION' }));

// will stop DELAYED_ACTION from firing
subscription.unsubscribe();

Other API Notes

The second argument to your dispatched function will be the store instance itself. This gives you the ability to getState() on your store in case you need to assert some condition before dispatching your next async message. It also gives you the ability to dispatch() explicitly.

Basic Dispatch Type Signature

If it helps to think about it this way, in a TypeScript-style type definition, the dispatch function would look like this when used to dispatch an action asynchronously:

dispatch = ((actions?: Observable<Action>, store?: ReduxStore) => Observable<Action>) => Subscription;

Example

A full example is available in examples/basic


Incompatible w/ redux-thunk

Since redux-observable uses dispached functions, this middlware is incompatible with redux-thunk. At this time, this is unavoidable since providing the function a stream of future actions for cancellation is imperative.

:shipit:

redux-observable's People

Contributors

benlesh avatar jayphelps avatar greenkeeperio-bot avatar bennett000 avatar robertnovo avatar sebald avatar timtyrrell avatar

Stargazers

Tomasz Jałoszyński avatar

Watchers

Tomasz Jałoszyński avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.