marko-js-samples / marko-express

Sample Express-based server app that integrates the marko module for rendering a view
20 stars 16 forks source link

Lasso-body breaks components #4

Closed DavidBernal closed 6 years ago

DavidBernal commented 6 years ago

Seems lasso-body load 2 times the components.

Preconditions: Download this repo

How to reproduce:

Current behavior: The headers are rendered. Javascript console show errors. Some funcionalities doesn't work correctly.

Expected behavoir: The global.req.headers is never rendered or no errors are shown.

Extra: If you delete JS part in app-hello/index.marko, then works correctly

patrick-steele-idem commented 6 years ago

This is expected. You will see the following errors in the Console for your browser:

Uncaught TypeError: Cannot read property 'headers' of undefined
    at render (index.marko.js:36)
    at renderer (renderer.js:186)
    at Component.js:469
    at Object.batchUpdate [as ___batchUpdate] (update-manager.js:63)
    at Component.___rerender (Component.js:458)
    at initComponent (init-components-browser.js:103)
    at init-components-browser.js:261
    at Array.forEach (<anonymous>)
    at Object.initServerRendered [as concat] (init-components-browser.js:198)
    at localhost/:51

In order to recreate the UI component tree rendered on the server, Marko will automatically do a rerender of the top-level UI component (passing it the same input that was given on the server) and this will rebuild UI component tree. out.global.req is only available on the server. You could do the following:

<p if(out.global.req)>
  ${JSON.stringify(out.global.req.headers)}
</p>

However, just keep in mind that the <p> tag with the headers rendered on the server will be removed from the DOM after the client rerender.

If you do need certain global data used on the server you can explicitly tell Marko to serialize specific global properties to the browser: http://markojs.com/docs/server-side-rendering/#serializing-globals

NOTE: You would probably not want to serialize out.global.req since it includes a lot of extra data.

DavidBernal commented 6 years ago

Sorry @patrick-steele-idem, but I don't understand. Another example.... (this doesn't show errors but is confused for me) In server.js I added a global attribute as you say:

app.get('/', function(req, res) {
    res.marko(indexTemplate, {
            $global:{
                prop: 'Global name'  // global property
            },
            name: 'Frank',
            count: 30,
            colors: ['red', 'green', 'blue']
        });
});

Now I would use out.global.porp in app-hello/index.marko:

<p>Hello ${input.name}</p>
<p>Hello ${out.global.prop}</p> <!-- new global property -->
<div.count>
  ${state.count}
</div>

But when I run the server, it is showed 300ms aprox.

Hoverwhere, if I delete the class in app-hello/index.marko runs correctly:

/* class {
  onCreate() {
    this.state = {
      count: 0
    }
  }

  onMount() {
    console.log('Mounted in the browser!');
  }

  increment() {
    this.state.count++;
  }
} */

style {
    .count {
        color:#09c;
        font-size:3em;
    }
    .example-button {
        font-size:1em;
        padding:0.5em;
    }
}

<p>Hello ${input.name}</p>
<p>Hello ${out.global.prop}</p>
<div.count>
  No state
</div>

<button type="button" on-click('increment')>
  Click me
</button>

Am I doing anything wrong?

Thank you for your pacient.