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

Avatar for Ivan Jovanovic

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;