aknuds1
aknuds1

Reputation: 68127

Why does my isomorphic Cycle.js app cause an xstream exception when rendering on server?

I am trying to write a demo isomorphic Cycle.js/Hapi.js app, but it fails with an exception in xstream while rendering on the server. What is going wrong here? I've based my app on Cycle.js' isomorphic app example.

The traceback looks like this:

TypeError: Uncaught error: s[i]._add is not a function
    at CombineProducer._start (/Users/arve/Projects/hapi-cycle/node_modules/xstream/core.js:190:22)
    at Stream._add (/Users/arve/Projects/hapi-cycle/node_modules/xstream/core.js:976:19)
    at MapOperator._start (/Users/arve/Projects/hapi-cycle/node_modules/xstream/core.js:717:18)
    at Stream._add (/Users/arve/Projects/hapi-cycle/node_modules/xstream/core.js:976:19)
    at LastOperator._start (/Users/arve/Projects/hapi-cycle/node_modules/xstream/core.js:596:18)
    at Stream._add (/Users/arve/Projects/hapi-cycle/node_modules/xstream/core.js:976:19)
    at Stream.addListener (/Users/arve/Projects/hapi-cycle/node_modules/xstream/core.js:1050:14)
    at Object.streamSubscribe (/Users/arve/Projects/hapi-cycle/node_modules/@cycle/xstream-adapter/lib/index.js:39:16)
    at /Users/arve/Projects/hapi-cycle/node_modules/@cycle/base/lib/index.js:49:30
    at Array.map (native)

The render code looks basically as follows:

import Cycle from '@cycle/xstream-run'
import xs from 'xstream'
import {html, section, h1, p, head, title, body, div, script, makeHTMLDriver,} from '@cycle/dom'
import serialize from 'serialize-javascript'
import Logger from '@arve.knudsen/js-logger'
let logger = Logger.get('server.rendering')

let wrapVTreeWithHtmlBoilerplate = ([vtree, context,]) => {
  return (
    html([
      head([
        title('Cycle Isomorphism Example'),
      ]),
      body([
        div('.app-container', [vtree,]),
        script(`window.appContext = ${serialize(context)};`),
        // script(clientBundle),
      ]),
    ])
  );
}

let main = (sources) => {
  let vtree = (
    section('.home', [
      h1('The homepage'),
      p('Welcome to our spectacular web page with nothing special here.'),
    ])
  )
  return {
    DOM: vtree,
  }
}

let renderIndex = (request, reply) => {
  let context = xs.of({})
  Cycle.run((sources) => {
    let vtree = main(sources).DOM
    let wrappedVTree = xs.combine(vtree, context)
      .map(wrapVTreeWithHtmlBoilerplate)
      .last()
    return {
      DOM: wrappedVTree,
    };
  }, {
    DOM: makeHTMLDriver((html) => {
      let wrappedHtml = `<!doctype html>${html}`
    }),
    context: () => {return context},
    PreventDefault: () => {},
  })
}

You can find the full source code here.

I'm running on OS X using Node v6.6.0, babel-node 6.14.0, Hapi 15.0.3, @cycle/dom 12.2.5 and @cycle/xstream-run 3.1.0. Let me know if you need more info.

Upvotes: 0

Views: 225

Answers (1)

aknuds1
aknuds1

Reputation: 68127

The reason for the error was that the rendered VTree was not a stream. I changed the code to the following and it works:

let vtree = sources.context.map(({}) => {
   return (
    section('.home', [
      h1('The homepage'),
      p('Welcome to our spectacular web page with nothing special here.'),
    ])
  )
})
return {
  DOM: vtree,
}

The sources.context.map call (which I borrowed from the original isomorphic example) ensures that vtree is a stream.

Upvotes: 1

Related Questions