Last active
February 9, 2017 13:29
-
-
Save tweinfeld/c7ec6af6be2376a7bbb2ef23d78ca863 to your computer and use it in GitHub Desktop.
React without Redux or Cycle.js
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
const | |
[div, span, button] = ["div", "span", "button"].map((name)=>React.createFactory(name)), | |
myCounterComponent = function({ count, callback }){ | |
return div({}, [], | |
button({ onClick: ()=>callback('decrease') }, ["-"]), | |
span({}, [count]), | |
button({ onClick: ()=>callback('increase') }, ["+"]) | |
); | |
}, | |
myCounterCombo = function({ state: { counter_1, counter_2 }, callback }){ | |
return div({}, [], | |
myCounterComponent({ count: counter_1, callback: (action)=>{ callback({ action, counter: 1 }) } }), | |
myCounterComponent({ count: counter_2, callback: (action)=>{ callback({ action, counter: 2 }) } }), | |
); | |
}; | |
// Create a subject to "gap the bridge" between React's input and output events | |
let | |
mainEl = document.querySelector('main'), | |
subject = (function(emitter){ | |
return { | |
stream: Kefir.stream((kefirEmitter)=>(emitter = kefirEmitter.emit)).toProperty(), | |
emit: (value)=>emitter(value) | |
}; | |
})(() => {}); | |
// Create a stream of user-interaction changes, by responding to subject changes | |
let myCounterComponentUIStream = subject | |
.stream | |
.debounce(0) | |
.flatMapLatest((state)=>Kefir.stream((emitter)=>ReactDOM.render(myCounterCombo({ state, callback: emitter.emit }), mainEl))); | |
// Maintain each property differently | |
let | |
counter1Property = myCounterComponentUIStream.filter(({ counter })=>counter===1).scan((prevCount, { action })=>prevCount += (action === "increase" ? 1 : -1), 0), | |
counter2Property = myCounterComponentUIStream.filter(({ counter })=>counter===2).scan((prevCount, { action })=>prevCount += (action === "increase" ? 2 : -2), 0); | |
// Combine properties into big state to be fed into React | |
Kefir | |
.combine([counter1Property, counter2Property]) | |
.map(([counter1Value, counter2Value])=>({ counter_1: counter1Value, counter_2: counter2Value })) | |
.onValue(subject.emit); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment