Skip to content

Instantly share code, notes, and snippets.

@abiodun0
Created February 26, 2017 22:02
Show Gist options
  • Save abiodun0/fd0eaf6498b2189282e3177e071b6f96 to your computer and use it in GitHub Desktop.
Save abiodun0/fd0eaf6498b2189282e3177e071b6f96 to your computer and use it in GitHub Desktop.
using observables with reactive-stream
import { isObservable } from './utils';
// Action creator
const actionCreator = (func) => (...args) => {
const action = func.call(null, ...args);
action$.next(action);
if (isObservable(action.payload))
action$.next(action.payload);
return action;
};
// method called from button click
const loadUsers = actionCreator(() => {
return {
type: 'USERS_LOADING',
payload: Observable.ajax('/api/users')
.map(({response}) => map(response, 'username'))
.map((users) => ({
type: 'USERS_LOADED',
payload: users
}))
};
});
// Reducer
export default function reducer(state, action) {
switch (action.type) {
case 'USERS_LOADING':
return {
...state,
isLoading: true
};
case 'USERS_LOADED':
return {
...state,
isLoading: false,
users: action.payload,
};
//...
}
}
// rest of code...
// Wrap input to ensure we only have a stream of observables
const ensureObservable = (action) =>
isObservable(action)
? action
: Observable.from([action]);
// Using flatMap to squash async streams
const action$
.flatMap(wrapActionToObservable)
.startWith(initState)
.scan(reducer);
import React from 'react';
import ReactDOM from 'react-dom';
import { Subject } from 'rxjs/Subject';
// create our stream as a subject so arbitrary data can be sent on the stream
const action$ = new Subject();
// Initial State
const initState = { name: 'Harry' };
// Redux reducer
const reducer = (state, action) => {
switch(action.type) {
case 'NAME_CHANGED':
return {
...state,
name: action.payload
};
default:
return state;
}
}
// Reduxification
const store$ = action$
.startWith(initState)
.scan(reducer);
// Higher order function to send actions to the stream
const actionDispatcher = (func) => (...args) =>
action$.next(func(...args));
// Example action function
const changeName = actionDispatcher((payload) => ({
type: 'NAME_CHANGED',
payload
}));
// React view component
const App = (props) => {
const { name } = props;
return (
<div>
<h1>{ name }</h1>
<button onClick={() => changeName('Harry')} >Harry</button>
<button onClick={() => changeName('Sally')} >Sally</button>
</div>
);
}
// subscribe and render the view
const dom = document.getElementById('app');
store$.subscribe((state) =>
ReactDOM.render(<App {...state} />, dom));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment