RxJS + React + Redux

RxJS Primer

Reactive Programming

  • Reactive programming is an asynchronous programming paradigm concerned with the data streams and propagation of change.
  • It treats the events happening in the app as an Asynchronous Data Streams.
  • Streams are a set of data, with a dimension of time.
  • Standardised by ECMAScript

Observables & Observers

Observable: Simply put, an observable is a stream of events than can be observed or listened to.

Observer:  Observer are the objects that subscribes/listens to an Observable.

Observables & Observers

Observable: Simply put, an observable is a stream of events than can be observed or listened to.

Observer:  Observer are the objects that subscribes/listens to an Observable.

import Observable from 'rxjs/Observable';


const pulseStream = Observable.create(observer => {
    
    observer.next(72);
    
    setTimeout(() => observer.next(80), 1000);

    setTimeout(() => observer.next(60), 2000);

});


pulseStream.subscribe(data => {

  console.log(data);

})


/*
Output is 
72
80
60
*/

Why Observables?

To handle asynchrony.  

We can handle it already in two ways:

  • Callbacks
  • Promises

 

Problems associated with callbacks:

Callback Hell

 

Problems associated with Problems:

  • Guaranteed Future
  • Immutability
  • Single Run

Operators

RxJS Api exposes a lot of stream creation & transformation operators

 

 

Rx.Observable.Of

The simplest creation operator of all.

This operator creates an Observable that emits the values you specify as arguments, immediately one after the other, and then emits a complete notification

const numbers = Rx.Observable.of(10, 20, 30);
numbers.subscribe(x => {
  console.log(x);
}, err => {
  console.log(err);
}, () => {
  console.log('done');
});

//output
/*
10
20
30
done
*/

Rx.Observable.fromEvent

fromEvent method creates an Observable that emits events of a specific type coming from the given event target.


const clickOb = Rx.Observable.fromEvent(document, 'click');
clickOb.subscribe(ev => console.log(ev));

Rx.Observable.fromPromise

fromPromise method simply converts a promise in to an Observable.It returns an Observable that just emits the Promise’s resolved value, then completes.


const result = Rx.Observable.fromPromise(fetch('http://myserver.com/'));
result.subscribe(x => console.log(x), e => console.error(e));

Rx.Observable.interval

interval operator creates an Observable that emits sequential numbers every specified interval of time.It starts with 0 and it never ends.


var numbers = Rx.Observable.interval(1000);
numbers.subscribe(x => console.log(x));

// output
/*
1
2( 1 second later)
3( 1 second later)
4( 1 second later)
5( 1 second later)
. . .
*/

Rx.Observable.timer

Timer creates an Observable that starts emitting after an initialDelay and emits ever increasing numbers after each period of time thereafter.


const numbers = Rx.Observable.timer(3000, 1000);
numbers.subscribe(x => console.log(x));

Transformation Operators

Rx.Observable.prototype.map

Transforms the items emitted by an Observable by applying a function to each item

var clicks = Rx.Observable.fromEvent(document, 'click');
var positions = clicks.map(ev => ev.clientX);
positions.subscribe(x => console.log(x));

Rx.Observable.prototype.filter

Transforms the items emitted by an Observable by applying a function to each item

var clicks = Rx.Observable.fromEvent(document, 'click');
var clicksOnDivs = clicks.filter(ev => ev.target.tagName === 'DIV');
clicksOnDivs.subscribe(x => console.log(x));

Rx.Observable.prototype.buffer

Collect output values from the given observable until the other observable emits

var clicks = Rx.Observable.fromEvent(document, 'click');
var interval = Rx.Observable.interval(1000);
var buffered = interval.buffer(clicks);
buffered.subscribe(x => console.log(x));

Usage with Redux

Usage with Redux

redux-observable

redux-observable

RxJS 5-based middleware for Redux. Compose and cancel async actions to create side effects and more.

Installation

npm install --save redux-observable

Epics

  • An Epic is the core primitive of redux-observable.
  • It is a function which takes a stream of actions and returns a stream of actions. Actions in, actions out.

Signature

function (action$: Observable<Action>, store: Store): Observable<Action>;

The actions you emit will be immediately dispatched through the normal store.dispatch(), so under the hood redux-observable effectively does epic(action$, store).subscribe(store.dispatch)

Epic for AutoComplete

Epic for AutoComplete with Cancellation

Combining Epics

import { combineEpics } from 'redux-observable';

const rootEpic = combineEpics(
  pingEpic,
  fetchUserEpic
);

equivalent to

import { merge } from 'rxjs/observable/merge';

const rootEpic = (action$, store) => merge(
  pingEpic(action$, store),
  fetchUserEpic(action$, store)
);

Configuring the Store

import { createEpicMiddleware } from 'redux-observable';
import { rootEpic, rootReducer } from './modules/root';

const epicMiddleware = createEpicMiddleware(rootEpic);

const store = createStore(
    rootReducer,
    applyMiddleware(epicMiddleware)
);

Benefits of redux-observable

  • Makes it easier to compose and control complex async tasks, over any amount of time
  • You don't need to manage your own Rx subscriptions
  • You can use redux tooling

Thanks

@paramsingh_66174

Questions & Musings

References

RxJS, React & Redux

By Param Singh