Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSR vs Browser results in different classnames and ReactDOM.hydrate mismatch :( #714

Open
cphoover opened this issue Apr 1, 2021 · 3 comments

Comments

@cphoover
Copy link

cphoover commented Apr 1, 2021

Bug

What is the current behavior?

Summary: I'm converting my site into a static generated site. I'm using ReactDOMServer.renderToString and flush from 'styled-jsx/server' in a node.js pipeline to render the static assets. Then when the client runtime loads I am using ReactDOM.hydrate to attempt to hydrate the application without a full render. Unfortunately it is re-rendering and a big white flash happens....

I investigated by doing a diff on the HTML of my application without JavaScript enabled against the HTML after the ReactDOM.hydrate step occurs and the application is re-rendered. The only differences I see are the styled-jsx classnames being different... How are hashes being generated? Are they deterministic? Do they take into account logical components as well as dom-elements in their generation?

Is it possible to have the following output where everything is identical except for the styled-jsx classnames:

<a href="#main-content" tabindex="0" class="jsx-998058316 ada-skip-link">Skip to content</a>
<div data-metrics-location="HDR" class="jsx-3222006434 global-utility-navigation-wrapper">
<a href="undefined#main-content" tabindex="0" class="jsx-998058316 ada-skip-link">Skip to content</a>
<div data-metrics-location="HDR" class="jsx-2836309959 global-utility-navigation-wrapper">

notice the class on the .global-utility-navigation-wrapper has the class jsx-3222006434 in the first example but jsx-2836309959 in the second example.

This causes a mismatch and rerender when trying to rehydrate the page.

image

@giuseppeg
Copy link
Collaborator

giuseppeg commented Apr 1, 2021

The hash should be deterministic.

See
https://github.com/vercel/styled-jsx/blob/master/src/_utils.js#L192-L228

and
https://github.com/vercel/styled-jsx/blob/master/src/stylesheet-registry.js#L134-L150

Do you have dynamic styles? The issue could also be due to the fact that you are hydrating multiple roots. Currently the styles registry is a singleton but there is a PR to enable multiple registries #703

@cphoover
Copy link
Author

cphoover commented Apr 12, 2021

@giuseppeg hmmm after digging deeper I discovered more...

(I compared the strings being passed into the hashString function and the resultant hash)

I realize that when I call flush it is actually passing a different string to the hashString function. When I inspect the strings using diff I realize that the css passed to hashString in the the build + babel transpilation process do not include the webkit prefix however the SSR flush actually includes a -webkit- vendor prefix on certain css rules when passed to hashString

image

Above you can see a csv surrounded with quotations with columns Filename of styles, Resultant Hash, Input text
You can see how their is a difference in the hash and the vendor prefix

image
^^ In many other parts of places the same thing is happening, and it seems to be the only difference between the two input strings (the -webkit- prefix)!

@cphoover
Copy link
Author

cphoover commented Apr 14, 2021

> Do you have dynamic styles?

No I searched through the project and there are no dynamic styles.

The issue could also be due to the fact that you are hydrating multiple roots

@giuseppeg I changed it so they are both hydrating the same root, and it still happens.
I will try and recreate in a simplified example and post

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants