Search code examples
javascriptrxjscyclejs

Issue using components in Cycle.js


I'm just getting started with Cycle.js, loving it so far but I'm having some issues componentizing my app.

I have this component which I want to import later from an other one:

// components/header.js

function intent (DOMSource, localStorage) {
  const menuClick$ = DOMSource.select('.header .menu').events('click')

  return {
    menuClick$,
  }
}

function model (menuClick$) {
  const menuToggle = menuClick$
    .startWith(false)
    .mapTo(1)
    .fold((acc, x) => acc + x, 0)
    .map(x => x % 2 === 0)

  return xs
  .combine(
    menuToggle,
  ).map(([toggle]) => ({
    toggle,
  }))
}

function view (state$) {
  return state$.map(state => (
    <header className="header" style={header}>
      <div className="menu" style={menu}>
        <div className="user" style={container}>
          <div className="image" style={image} />
          <div className="name" style={user}>Karen Serfaty</div>
          <div className="arrow" style={arrow} />
        </div>
        { state.toggle
          ? <div className="items" style={list}>
              <span id="logout">Cerrar sesión</span>
            </div>
          : <div />
        }
      </div>
    </header>
  ))
}

function Header (sources) {
  const {
    menuClick$,
  } = intent(sources.DOM)

  const state$ = model(menuClick$)
  const vtree$ = view(state$)

  return {
    DOM: vtree$,
  }
}

export default Header

And I want to import it here:

// components/index.js

import { html } from 'snabbdom-jsx';
import xs from 'xstream'

import Header from './header'

function main (sources) {
  const header = Header(sources)

  const vtree$ = xs.of(
    <span>
      {header.DOM}
    </span>
  )

  return {
    DOM: vtree$
  }
}

export default main

And here is the root of the app:

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

import main from './components'

const drivers = {
  DOM: makeDOMDriver('#app'),
}

run(main, drivers)

If I import the Header component directly to the root of the app it works fine so I'm guessing there is something wrong in my components/index.js file?

-- Edit --

I forgot to mention that when I run the code I'm getting an undefined on the browser.


Solution

  • your const header is an object of streams that looks like this

    { DOM: vTree$ }

    to make use of it, you should do something like this...

    // components/index.js
    
    import { html } from 'snabbdom-jsx';
    import xs from 'xstream';
    
    import Header from './header';
    
    function main (sources) {
      const header = Header(sources)
    
      const vtree$ = header.DOM.map( headerVNode => (
        <span>
          { headerVNode }
        </span>
      ));
    
      return {
        DOM: vtree$
      }
    }
    
    export default main;