kriasoft / hyperapp-render

Render Hyperapp to an HTML string with SSR and Node.js streaming support.
MIT License
103 stars 15 forks source link

Usage with Hyperapp 2 #17

Closed Siilwyn closed 11 months ago

Siilwyn commented 4 years ago

I'm submitting a ...

Documentation request

It looks like the readme shows usage with Hyperapp 1? I can't really figure out how to do this with Hyperapp 2.

frenzzy commented 4 years ago

Hi! The only difference is there no actions in v2, but API and usage is the same:

Usage with Hyperapp v1:

import { renderToString, renderToStream } from 'hyperapp-render'

renderToString(<Component />)        // => <string>
renderToString(view(state, actions)) // => <string>
renderToString(view, state, actions) // => <string>

renderToStream(<Component />)        // => <stream.Readable> => <string>
renderToStream(view(state, actions)) // => <stream.Readable> => <string>
renderToStream(view, state, actions) // => <stream.Readable> => <string>

Usage with Hyperapp v2:

import { renderToString, renderToStream } from 'hyperapp-render'

renderToString(<Component />)        // => <string>
renderToString(view(state))          // => <string>
renderToString(view, state)          // => <string>

renderToStream(<Component />)        // => <stream.Readable> => <string>
renderToStream(view(state))          // => <stream.Readable> => <string>
renderToStream(view, state)          // => <stream.Readable> => <string>

In case if you need a full demoable example with v2, see CodePen:

import { h } from 'hyperapp'
import { renderToString } from 'hyperapp-render'

const state = {
  text: 'Hello'
}

const actions = {
  setText: (state, event) => ({
    ...state,
    text: event.target.value,
  }),
}

const view = (state) => (
  <main>
    <h1>
      {state.text.trim() === '' ? '👋' : state.text}
    </h1>
    <input
      value={state.text}
      oninput={actions.setText}
    />
  </main>
)

const html = renderToString(view(state))

console.log(html) // => <main><h1>Hello</h1><input value="Hello"/></main>
Siilwyn commented 4 years ago

Ah thank you, I got something working with a bit of monkeypatching! Maybe it would make sense to change the examples in the readme to version two since it's the default version of hyperapp?

There are two issues to running the example you posted in Node.js 14 natively:

  1. hyperapp-render doesn't seem to export renderToString directly so first it's needed to import the whole module and use that variable to access the method.
  2. hyperapp doesn't export an ESM module at all so for now have to patch the main exported file to be index.mjs instead of index.js.

So doing the above would make this run:

import hyperappRender from 'hyperapp-render';
import { h } from 'hyperapp';

const state = {
  text: 'Hello'
}

const actions = {
  setText: (state, event) => ({
    ...state,
    text: event.target.value,
  }),
}

const view = (state) => (
  h('main', {}, [
    h('h1', {}, state.text)
  ])
)

const html = hyperappRender.renderToString(view(state))

console.log(html) // => <main><h1>Hello</h1><input value="Hello"/></main>

The second issue is of course not an issue for this project but it would be nice for the first to be fixed, want me to make another issue?

frenzzy commented 4 years ago

Just released v3.4.0 with ESM support for the latest Node.js. It should fix the first issue you mentioned.

About Hyperapp v2, in my opinion it is not ready yet. It does not have documentation and tests, breaking changes are still considered, there were no an official announcement that v2 is ready. Also as you noticed it it does not properly export h to be used in Node.js which makes it hard to write a proper tests here in hyperapp-render for hyperapp v2. So, I don't want to update examples and pay attention to v2 in readme until it is ready to use. Hope you see now my point.

Siilwyn commented 4 years ago

Understandable, thank you for your effort! I assumed version two was ready but that seems like a wrong assumption on my part.

Let's keep this issue open until v2 is ready? Feel free to close though.

talentlessguy commented 4 years ago

Doesn't look like working with Hyperapp 2 at all.

Versions

Code

import { App } from '@tinyhttp/app'
import { h, text } from 'hyperapp'
import { renderToString } from 'hyperapp-render'

const state = {
  text: 'Hello',
}

const view = (state) => h('main', {}, [h('h1', {}, [text(state.text)]), h('input', { value: 'bruh' })])

const app = new App()

app
  .get((_, res) => {
    const html = renderToString(view(state))

    console.log(html)

    res.send(html)
  })
  .listen(3000, () => console.log(`Listening on http://localhost:3000`))

Link to the example: https://github.com/talentlessguy/tinyhttp/blob/master/examples/hyperapp-ssr

Current Result

$ curl localhost:3000
# absolutely nothing

Expected result

$ curl localhost:3000
<main>
<h1>Hello</h1>
<input value="bruh" />
</main>

Additional notes

renderToStream doesn't produce anything as well. nothing is rendered.

frenzzy commented 4 years ago

@talentlessguy thank you! Just released v3.5.0 :tada: with support for Hyperapp v2.0.6-v2.0.8. Demo: CodePen

talentlessguy commented 4 years ago

@frenzzy hurray it works!! thanks

talentlessguy commented 3 years ago

Should this be closed? Because currently there are no issues with Hyperapp 2

frenzzy commented 3 years ago

This issue is about documentation - how to use hyperapp-render with hyperapp v2, but since hyperapp v2 is not officially released yet and may introduce new breaking changes we are just waiting here.