Cycle.js: Functional and Reactive
-
Upload
eugene-zharkov -
Category
Technology
-
view
851 -
download
0
Transcript of Cycle.js: Functional and Reactive
EXISTED APPLICATION DATA FLOW | FLUX / REDUX
VIEW
DISPATCHERSTORE
actio
nac
tion
actio
n
STORE
USER ACTION
EXISTED APPLICATION DATA FLOW | MODEL VIEW INTENT
VIEW
INTENT
MODEL
USER ACTION
observable
observable
observable
CODE EXAMPLEfunction intent(DOM, name = '') { const removeClicks$ = DOM.select('.remove-btn').events('click'); const stop$ = removeClicks$; const remove$ = removeClicks$.delay(500); return {stop$, remove$}; }
function model(actions, givenColor$) { const x$ = Observable.interval(50).startWith(0).takeUntil(actions.stop$); const y$ = Observable.interval(100).startWith(0).takeUntil(actions.stop$); const color$ = Observable.merge( givenColor$.takeUntil(actions.stop$), actions.stop$.map(() => '#FF0000') ); return combineLatestObj({x$, y$, color$}); }
function view(state$) { return state$.map(({color, x, y}) => { const style = {color, backgroundColor: '#ECECEC'}; return div('.ticker', {style}, [ h4(`x${x} ${color}`), h1(`Y${y} ${color}`), button('.remove-btn', 'Remove') ]); }); }
BUTTON CLICK
HTML GENERATION
COLOR CHANGE
JSBIN.COM/VUGARUR/
BASIC EXAMPLEimport Cycle from '@cycle/core'; import {div, label, input, hr, h1, makeDOMDriver} from '@cycle/dom';
function main(sources) { return { DOM: sources.DOM.select('.myinput').events('input') .map(ev => ev.target.value) .startWith('') .map(name => div([ label('Name:'), input('.myinput', {attributes: {type: 'text'}}), hr(), h1(`Hello ${name}`) ]) ) }; }
Cycle.run(main, { DOM: makeDOMDriver('#main-container') });
JSBIN.COM/VUGARUR/
BASIC EXAMPLEimport Cycle from '@cycle/core'; import {div, label, input, hr, h1, makeDOMDriver} from '@cycle/dom';
function main(sources) { return { DOM: sources.DOM.select('.myinput').events('input') .map(ev => ev.target.value) .startWith('') .map(name => div([ label('Name:'), input('.myinput', {attributes: {type: 'text'}}), hr(), h1(`Hello ${name}`) ]) ) }; }
Cycle.run(main, { DOM: makeDOMDriver('#main-container') });
HANDLE EVENTGET INPUT VALUE
DEFAULT VALUE
HTML
JSBIN.COM/VUGARUR/
BASIC EXAMPLEimport Cycle from '@cycle/core'; import {div, label, input, hr, h1, makeDOMDriver} from '@cycle/dom';
function main(sources) { return { DOM: sources.DOM.select('.myinput').events('input') .map(ev => ev.target.value) .startWith('') .map(name => div([ label('Name:'), input('.myinput', {attributes: {type: 'text'}}), hr(), h1(`Hello ${name}`) ]) ) }; }
Cycle.run(main, { DOM: makeDOMDriver('#main-container') });
DOM..DRIVER..???
TEXT
DRIVER
▸ DRIVER - effect, “action”
▸ HTTP, WebSocket, User Event, Browser Event etc
▸ SINK - Observable input
JSBIN.COM/LELUHO
SINKfunction main () { return Rx.Observable.timer(0, 1000) .map(i => `Seconds elapsed ${i}`); }
function htmlEffect(text$) { text$.subscribe(text => { const container = document.querySelector('#main'); container.textContent = text; }) }
function consoleEffect(msg$) { msg$.subscribe(msg => console.log(msg)); }
const sink = main(); htmlEffect(sink); consoleEffect(sink);
STREAM GOT INPUT
STEP BY STEP EFFECT
JSBIN.COM/VUGARUR/
BASIC EXAMPLE .map(name => div([ label('Name:'), input('.myinput', {attributes: {type: 'text'}}), hr(), h1(`Hello ${name}`) ]) ) }; }
Cycle.run(main, { DOM: ……….. });
CYCLE RUN
GITHUB.COM/CYCLEJS/CORE/BLOB/MASTER/SRC/CYCLE.JS
CYCLE.RUNfunction run(main, drivers) { if (typeof main !== `function`) { throw new Error(`First argument given to Cycle.run() must be the 'main' ` + `function.`) } if (typeof drivers !== `object` || drivers === null) { throw new Error(`Second argument given to Cycle.run() must be an object ` + `with driver functions as properties.`) } if (Object.keys(drivers).length === 0) { throw new Error(`Second argument given to Cycle.run() must be an object ` + `with at least one driver function declared as a property.`) }
let sinkProxies = makeSinkProxies(drivers) let sources = callDrivers(drivers, sinkProxies) let sinks = main(sources) let subscription = replicateMany(sinks, sinkProxies).subscribe() let sinksWithDispose = attachDisposeToSinks(sinks, subscription) let sourcesWithDispose = attachDisposeToSources(sources) return {sources: sourcesWithDispose, sinks: sinksWithDispose} }
TEXT
RESOURCES
▸ https://jsbin.com/zizabe/
▸ https://jsbin.com/xataxe/
▸ https://jsbin.com/vugarur
▸ https://jsbin.com/dogumi
▸ egghead.io