Skip to content

Instantly share code, notes, and snippets.

@tweinfeld
Last active February 9, 2017 13:29
Show Gist options
  • Save tweinfeld/c7ec6af6be2376a7bbb2ef23d78ca863 to your computer and use it in GitHub Desktop.
Save tweinfeld/c7ec6af6be2376a7bbb2ef23d78ca863 to your computer and use it in GitHub Desktop.
React without Redux or Cycle.js
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