#Set State() of pre-rendered component from external API call response

1 messages · Page 1 of 1 (latest)

tulip cosmos
#

I'm pre-rendering my website with (non-shadowdom) components. It all works great and is feast and SEO friendly.

However one component reads data from external APIs and renders differently depending on the data. On the client when the component hydrates and I don't wanna reload this data for the render to result in the same outcome (=DOM).

Is there a way to "pass" the data loaded on the prerender run on the server into the components "hydrate state" ?

grand acorn
#

there's ways ... I did something along the lines of:

  • fetch the data server side
  • make a prop to inject the data into the component

You could either:

  • make the prop a string then de/serialise json to it < I didn't use this route as I didn't like the idea of big json blobs being in the markup.
  • use the createWindowFromHtml exported from your hydrate script. This creates a live 'dom' object (MockDoc) in node < with that you can add complex props server-side.
    Total code looks something like:
  import {
    renderToString,
    createWindowFromHtml,
  } from '@your-things/hydrate/index.js'
  ....
  const win = createWindowFromHtml(preRenderedResponse, 'stencil-ssr');
  const document = win.document;
  const ele = document.querySelector('myElement');
  Object.assign(ele, {complexProp: nodeFetchedObject });
  await renderToString(document);
tulip cosmos
#

Hey @grand acorn ! Thanks for getting back.

So createWindowFromHtmlis something Stencil provides from the dist-hydrate-script output target?

grand acorn
#

Yep - undocumented things are fun!
Try for yourself - it should be there

tulip cosmos
#

I will.

I just tried one intermediate step. Which is blocking rendering (even the first one) with a Prop()but it still removes my pre-rendered content. Which looks like this:

    <!--r.21-->
    <co-view class="contact-page-book-demo-cta hydrated" c-id=21.0.0.0 s-id=22>
        <!--r.22-->
        <newsletter-signup class="newsletter-signup-tag-added hydrated" data-ca=6627601197627bf41a3813ee c-id=22.0.0.0 s-id=23>
            <some-more-tags />
        </newsletter-signup>
    </co-view>
</co-render-view>```

I have tried this code:

```  componentWillRender() {
    return this.reloadOnClient;
  }```

Any idea why the children of my custom element would get removed? If I disable Javascript it stays there. So something other then the `render`method is throwing it away.
grand acorn
#

a hydration mismatch? - code not found via the server render, but present in the first client render (or vice versa) will be unified / rationalised / removed

tulip cosmos
#

Sounds like it. So there is a hydration process which changes the inner DOM even before the first render?

Where would I look to learn more about this? I mean where in the code of Stencil.

And sorry for asking all these questions 🫣