Cycle "advanced" counter with parent state sharing

March 22, 2016 · View on GitHub

import Rx, {Observable as O} from "rx" import Cycle from "@cycle/core" import {h, makeDOMDriver} from "@cycle/dom" import isolate from "@cycle/isolate"

function Counter({DOM, initial}) { const mod = O.merge( DOM.select(".dec").events("click").map(ev => state => state - 1), DOM.select(".inc").events("click").map(ev => state => state + 1) ) const count=initial = initial.first().concat(mod$).scan((state, mod) => mod(state)).shareReplay(1)

return { DOM: count.map(count=>h("div",[h("button.inc","++"),h("button.dec",""),h("p","Counter:"+count)])),value.map(count => h("div", [ h("button.inc", "++"), h("button.dec", "--"), h("p", "Counter: " + count) ]) ), value: count$ } }

function main({DOM}) { const stateModProxy=newRx.Subject()conststate = new Rx.Subject() const state = stateModProxy$ .startWith({a: 0, b: 0}) .scan((state, mod) => mod(state)) .shareReplay(1)

const a = state.map(s => isolate(Counter, "a")({DOM, initial: O.just(s.a)})).shareReplay(1) const b = state.map(s => isolate(Counter, "b")({DOM, initial: O.just(s.b)})).shareReplay(1)

const resetMod=DOM.select(".reset").events("click").map(()=>()=>(a:0,b:0))constaChangeMod = DOM.select(".reset").events("click").map(() => () => ({a: 0, b: 0})) const aChangeMod = a.map(s => s.value.skip(1).first()).switch().map(val=>state=>(...state,a:val))constbChangeMod.skip(1).first()).switch().map(val => state => ({...state, a: val})) const bChangeMod = b.map(s => s.value$.skip(1).first()).switch().map(val => state => ({...state, b: val}))

const vdom=O.combineLatest(state = O.combineLatest(state, a.map(s => s.DOM).switch(), b.map(s => s.DOM).switch(), (state, a, b) => h("div", [ a, b, h("hr"), h("h2", Total: ${state.a + state.b}), h("button.reset", "Reset") ]))

O.merge(resetMod,aChangeMod, aChangeMod, bChangeMod).subscribe(stateModProxy).subscribe(stateModProxy) return {DOM: vdom$} }

Cycle.run(main, { DOM: makeDOMDriver("#main-container"), })