Skip to content
This repository has been archived by the owner on Nov 5, 2022. It is now read-only.

Latest commit

 

History

History
112 lines (97 loc) · 2.92 KB

cyclejs.md

File metadata and controls

112 lines (97 loc) · 2.92 KB

Cycle.js example

Install dependencies:

npm install xstream @cycle/run @cycle/dom @cycle/html

Create a server.js file in the project root:

import { Stream } from 'xstream'
import { run } from '@cycle/run'
import { makeHTMLDriver } from '@cycle/html'
import { html, head, body, title, script, link, div } from '@cycle/dom'

export default Component => (bundle, props) => new Promise(resolve => {
    const serializedProps = encodeURIComponent(JSON.stringify(props))
    const main = sources => {
        const component = Component(sources)
        const views = Stream.combine(sources.props, component.DOM).map(([props, view]) =>
            html([
                head([
                    title([props.title]),
                    link({ attrs: { href: bundle.stylesheet, rel: 'stylesheet' } })
                ]),
                body([
                    div('#root', { attrs: { 'data-props': serializedProps } }, [
                        view
                    ]),
                    script({ attrs: { src: bundle.script } })
                ])
            ])
        )
        return {
            DOM: views
        }
    }
    const drivers = {
        DOM: makeHTMLDriver(html => {
            dispose()
            resolve('<!DOCTYPE html>' + html)
        }),
        props: () => Stream.of(props)
    }
    const dispose = run(main, drivers)
})

Create a client.js file in the project root:

import { Stream } from 'xstream'
import { run } from '@cycle/run'
import { makeDOMDriver } from '@cycle/dom'

export default Component => {
    const container = document.getElementById('root')
    const props = JSON.parse(decodeURIComponent(container.dataset.props))
    const drivers = {
        DOM: makeDOMDriver(container),
        props: () => Stream.of(props)
    }
    run(Component, drivers)
}

Add custom scripts to settings.py:

'OPTIONS' : {
    'scripts': {
        'server': os.path.join(BASE_DIR, 'server.js'),
        'client': os.path.join(BASE_DIR, 'client.js'),
    }
}

Add a Django view and export the root component:

from django.shortcuts import render

def cycle_view(request):
    return render(request, 'template.js', context={
        'title': 'Django Cycle SSR',
        'count': 0
    })
import { Stream } from 'xstream'
import { h1, button, div } from '@cycle/dom'

export default sources => {
    const increments = sources.DOM.select('.increment').events('click').mapTo(1)
    const decrements = sources.DOM.select('.decrement').events('click').mapTo(-1)
    const counts = sources.props.map(props =>
        Stream.merge(increments, decrements).fold((acc, n) => acc + n, props.count)
    ).flatten()
    const views = counts.map(count =>
        div([
            h1('Count ' + count),
            button('.increment', '+'),
            button('.decrement', '-'),
        ])
    )
    return {
        DOM: views
    }
}