Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Digging into Cycle.js

Digging into Cycle.js

Introduction to Cycle.js framework

Ivan Jovanovic

March 25, 2017
Tweet

More Decks by Ivan Jovanovic

Other Decks in Technology

Transcript

  1. Features • Functional (just write pure functions) • Reactive •

    Testable • Composable • Explicit dataflow • Made for large codebases
  2. Drivers - side effects • HTTP • DOM • WebSockets

    • Local storage driver • HTML5 Notifications driver • …
  3. Cycle.js official packages • DOM - collection of drivers that

    work with DOM; it has DOM driver and HTML driver, based on snabdom virtual DOM library • History - driver for History API • HTTP - driver for HTTP requests, based on superagent • Isolate - function for making scoped dataflow components • Most-run - `run` function for apps made with `most` • Run - `run` function for apps made with `xstream` • RxJS-run - `run` function for apps made with `rxjs`
  4. import xs from 'xstream'; import { run } from '@cycle/run';

    import { div, button, p, makeDOMDriver } from '@cycle/dom'; function main(sources) { const action$ = xs.merge( sources.DOM.select('.decrement').events('click').map(ev => -1), sources.DOM.select('.increment').events('click').map(ev => +1) ); const count$ = action$.fold((acc, x) => acc + x, 0); const vdom$ = count$.map(count => div([ button('.decrement', 'Decrement'), button('.increment', 'Increment'), p('Counter: ' + count) ]) ); return { DOM: vdom$, }; } run(main, { DOM: makeDOMDriver('#main') });
  5. function main(sources) { const action$ = xs.merge( sources.DOM.select('.decrement').events('click').map(ev => -1),

    sources.DOM.select('.increment').events('click').map(ev => +1) ); const count$ = action$.fold((acc, x) => acc + x, 0); const vdom$ = count$.map(count => div([ button('.decrement', 'Decrement'), button('.increment', 'Increment'), p('Counter: ' + count) ]) ); return { DOM: vdom$, }; }
  6. View + CSS const style = { backgroundColor: 'blue', width:

    '60px', height: '60px' } const vdom$ = count$.map(count => div([ button('.decrement', { style }, ’Decrement’), button('.increment', { style }, ’Increment’), p('Counter: ' + count) ]) );
  7. import {makeHTTPDriver} from ‘@cycle/http'; function main(sources) { const request$ =

    xs.periodic(1000) .mapTo({ url: 'http://localhost:3000', category: 'api', }); const vtree$ = sources.HTTP.select('api') .flatten() .map(res => res.body) .startWith({ response: ‘’ }) .map(result => div([ h2('.label', `Response from the server: ${result.response}`) ]) ); return { DOM: vtree$, HTTP: request$ }; } run(main, { DOM: makeDOMDriver('#main'), HTTP: makeHTTPDriver() });
  8. function main(sources) { const request$ = xs.periodic(1000) .mapTo({ url: 'http://localhost:3000',

    category: 'api', }); const vtree$ = sources.HTTP.select('api') .flatten() .map(res => res.body) .startWith({ response: ‘’ }) .map(result => div([ h2('.label', `Response from the server: ${result.response}`) ]) ); return { DOM: vtree$, HTTP: request$ }; }
  9. const vtree$ = sources.HTTP.select('api') .flatten() .map(res => res.body) .startWith({ response:

    '' }) .map(result => div([ h2('.label', `Response from the server: ${result.response}`) ]) );
  10. function LabeledSlider(sources) { const domSource = sources.DOM; const props$ =

    sources.props; const newValue$ = domSource .select('.slider') .events('input') .map(ev => ev.target.value); const state$ = props$ .map(props => newValue$ .map(val => ({ label: props.label, unit: props.unit, min: props.min, value: val, max: props.max })) .startWith(props) ); const vdom$ = state$ .map(state => div('.labeled-slider', [ span('.label', `${state.label} ${state.value}${state.unit}` ), input('.slider', { attrs: {type: 'range', min: state.min, max: state.max, value: state.value} }) ]) ); const sinks = { DOM: vdom$, value: state$.map(state => state.value), }; return sinks; }
  11. import isolate from '@cycle/isolate'; const sliderSources = {DOM: sources.DOM, props:

    sliderProps$}; const slider = isolate(LabeledSlider)(sliderSources); const sliderVDom$ = slider.DOM; const sliderValue$ = slider.value;