Created
February 26, 2017 22:02
-
-
Save abiodun0/fd0eaf6498b2189282e3177e071b6f96 to your computer and use it in GitHub Desktop.
using observables with reactive-stream
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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