Skip to content

Instantly share code, notes, and snippets.

@IceOnFire
Created June 22, 2017 10:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IceOnFire/afd229648d6314d5d7d7cb59aa183c82 to your computer and use it in GitHub Desktop.
Save IceOnFire/afd229648d6314d5d7d7cb59aa183c82 to your computer and use it in GitHub Desktop.
Reducer-based Rx MVC Framework
import view from './view'
document.querySelector('#root').appendChild(view())
import { model } from './radx'
export const increment = () => ({ type: 'INCREMENT' })
export const decrement = () => ({ type: 'DECREMENT' })
export const initialState = { count: 0 }
export const getCount = state => state.count
const reducer = (state, action) => {
switch (action.type) {
case 'INCREMENT':
return Object.assign({}, state, {
count: state.count + 1
})
case 'DECREMENT':
return Object.assign({}, state, {
count: state.count - 1
})
default:
return state
}
}
export default model(reducer)
import Rx from 'rxjs/Rx'
export const model = reducer => action$ =>
action$.map(action => state => reducer(state, action))
export const view = (observer, initialState, ...observables) =>
Rx.Observable
.merge(...observables)
.startWith(initialState)
.scan((state, updateFn) => updateFn(state))
.subscribe(observer)
export const controller = (event, elem, action) =>
Rx.Observable.fromEvent(elem, event).map(action)
import { view, controller } from './radx'
import handle, { getCount, increment, decrement, initialState } from './model'
export default () => {
const incrementBtn = document.createElement('button')
incrementBtn.innerText = 'increment'
const decrementBtn = document.createElement('button')
decrementBtn.innerText = 'decrement'
const countSpan = document.createElement('span')
const wrapperDiv = document.createElement('div')
wrapperDiv.appendChild(incrementBtn)
wrapperDiv.appendChild(decrementBtn)
wrapperDiv.appendChild(countSpan)
const render = state => (countSpan.innerText = getCount(state))
const increment$ = controller('click', incrementBtn, increment)
const decrement$ = controller('click', decrementBtn, decrement)
view(render, initialState, handle(increment$), handle(decrement$))
return wrapperDiv
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment