question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Global component + advanced SSR doesn't hydrate as expected

See original GitHub issue

Current behavior:

When using the “advanced approach” (https://emotion.sh/docs/ssr#advanced-approach) to SSR in combination with the <Global> component, hydration doesn’t appear to be working as expected.

All non-global styles seem to be rehydrated properly, but styles included via <Global> are injected into to the page when the client bundle hydrates instead of rehydrating the existing server-provided global styles.

This leads to issues due to specificity where the global rules now have a chance to override non-globals, causing visual bugs.

From looking at the source, this appears to be because InnerGlobal checks if the global styles are already included on the page for rehydration purposes here: https://github.com/emotion-js/emotion/blob/c85378a204613885a356eaba1480c5151838c458/packages/core/src/global.js#L76

Unfortunately, this selector doesn’t match anything that would be produced by the “advanced approach” SSR guide, which suggests including:

<style data-emotion-css="${ids.join(' ')}">${css}</style>

on the page. So if the InnerGlobal has this.props.serialized.name of deadb33f, it’s expecting to see:

<style data-emotion-css="deadb33f">...</style>

on the page to know where to hydrate, which isn’t the case. The reality will look more like:

<style data-emotion-css="deadb33f s0meId an0th3rOne">...</style>

To reproduce:

TODO: cannot use the codesandbox since it’s not set up for SSR. Will make a repo if this helps, but want to post this first since I do think I know roughly why it’s happening.

Expected behavior:

The styles included in <Global> should be rehydrated in the same way as non-globals: i.e. any styles that are already included on the page via SSR should not be re-inserted.

I need to dig into how this is working for non-global styles, since presumably the logic is set up there to scan through the IDs included as part of the data-emotion-css attribute rather than expecting a single id per style tag.

I’m also not sure if there’s an existing way to use extractCritical to split up the css into multiple <style> tags - it seems like that would also fix it from the other direction, although the docs would likely need to be updated if that’s the way forward.

Environment information:

  • react version: 16.13.1
  • @emotion/core version: 10.0.35

Let me know if there’s any other info you need from me. I’ll try and spin up a repo if my snippets above don’t paint the full picture.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:7
  • Comments:18 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
Andaristcommented, Oct 21, 2020

I’ve looked into the repro (thank you for that!) - need to give this some more thought, for now gonna just describe what happens here:

  1. we are dealing with a compat cache here (if you are using extractCritical API we set automatically set the compat flag on the cache)
  2. for compat caches we don’t render style elements in the output for global styles
  3. but we insert them into the cache
  4. we don’t keep track in the cache which styles come from regular emotion styles and which are global
  5. because the extracted IDs are just in a single “bag” you put all of them into a single <style/> element
  6. this fails while rehydrating here
  7. because global styles can be removed at runtime we probably should separate those IDs as otherwise, we’d have to be able to manipulate the already SSRed .textContent of <style/> elements to remove those and we don’t do that now (and it’s also more complex/error-prone)
0reactions
Andaristcommented, Mar 7, 2021

I’m assuming we’d be able to release in v11 as it would be a new method rather than modifying existing APIs?

yes, exactly

Read more comments on GitHub >

github_iconTop Results From Across the Web

The Perils of Rehydration
A surprisingly-common misconception can lead to big rendering issues that are difficult to debug. This deep-dive tutorial examines how React ...
Read more >
React 18: Hydration failed because the initial UI does not ...
Hydration failed when the children was dangerously set inner HTML . Got rid of the component, and it works fine now. (I could...
Read more >
react-hydration-error
When css-in-js libraries are not set up for pre-rendering (SSR/SSG) it will often lead to a hydration mismatch. In general this means the...
Read more >
Server Side Rendering
You can also use the advanced integration, it requires more work but does not ... To use emotion's SSR with Next.js you need...
Read more >
Server-Side Rendering
To demonstrate SSR, you can use webpack to compile a client-side build that then gets picked up by a server that renders it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found