Top Banner
CYCLE.JS: FUNCTIONAL AND REACTIVE EUGENE ZHARKOV
21

Cycle.js: Functional and Reactive

Apr 12, 2017

Download

Technology

Eugene Zharkov
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Cycle.js: Functional and Reactive

CYCLE.JS: FUNCTIONAL AND REACTIVE

EUGENE ZHARKOV

Page 2: Cycle.js: Functional and Reactive

Cycle.js

virtual-domRxJS

cycle/corecycle/dom

Page 3: Cycle.js: Functional and Reactive

EXISTED APPLICATION DATA FLOW | FLUX / REDUX

VIEW

DISPATCHERSTORE

actio

nac

tion

actio

n

STORE

USER ACTION

Page 4: Cycle.js: Functional and Reactive

EXISTED APPLICATION DATA FLOW | MODEL VIEW INTENT

VIEW

INTENT

MODEL

USER ACTION

observable

observable

observable

Page 5: Cycle.js: Functional and Reactive

1A

B

2 3

C

I’m loving it

Page 6: Cycle.js: Functional and Reactive

RX UNDER THE HOOD

Page 7: Cycle.js: Functional and Reactive

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

Page 8: Cycle.js: Functional and Reactive

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') });

Page 9: Cycle.js: Functional and Reactive

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

Page 10: Cycle.js: Functional and Reactive

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..???

Page 11: Cycle.js: Functional and Reactive

TEXT

DRIVER

▸ DRIVER - effect, “action”

▸ HTTP, WebSocket, User Event, Browser Event etc

▸ SINK - Observable input

Page 12: Cycle.js: Functional and Reactive

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

Page 13: Cycle.js: Functional and Reactive

TEXT

SINK

Page 14: Cycle.js: Functional and Reactive

TEXT

RX PLAYGROUD

HTTP://RXMARBLES.COM

Page 15: Cycle.js: Functional and Reactive

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

Page 16: Cycle.js: Functional and Reactive

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} }

Page 17: Cycle.js: Functional and Reactive

BASIC DEMO

Page 18: Cycle.js: Functional and Reactive

HTTP DEMO

Page 19: Cycle.js: Functional and Reactive

JSX MIX DEMO

Page 20: Cycle.js: Functional and Reactive

THANK YOU

@2J2E [email protected]

!

Page 21: Cycle.js: Functional and Reactive

TEXT

RESOURCES

▸ https://jsbin.com/zizabe/

▸ https://jsbin.com/xataxe/

▸ https://jsbin.com/vugarur

▸ https://jsbin.com/dogumi

▸ egghead.io