-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[Avatar] fix initial server / client render mismatch #2751
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
Conversation
03b725a
to
a357d64
Compare
I will fix the conflicts in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've not tried this with an SSR rendering but it sounds like it'll do the trick.
I'd be interested to hear some thoughts from @dleroux and @tmlayton as they looked at this the first time around in #712. Entertainingly it sounds like this "trigger a second render" approach was the original solution but then Staff Engineers happened and it turns out you shouldn't do "isServer" because of this hydration mismatching :D (For fairness my initial thought of "do we need this, could we just render the Image on the server" was also neatly shot-down in that original PR)
return true; | ||
}, | ||
})); | ||
jest.mock('../../../utilities/use-is-after-initial-mount', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't feel like this test adds much value anymore, mocking out individual hooks feels like a weird smell. Do we care that much about initial renderings?
Strictly speaking this isn't even testing SSR rendering - it's a bad proxy of it by mocking out a single hook. I wonder if ideally react-testing should provide some version of mountOnServer
that renders a component using react-dom/server
(like the hack described in testing-library/react-testing-library#561), but that feels like a meaty problem for another day.
On a very petty note, we can save the explicit return:
jest.mock('../../../utilities/use-is-after-initial-mount', () => ({
useIsAfterInitialMount: () => false,
}));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me it provides the same value as before. Earlier we were pretending to be on a server environment by mocking a constant now we simulate that by mocking a hook. Even though I agree earlier it was more explicit. I also agree that a renderOnServer
function that doesn't mount would be pretty great for these cases. Do you want me to delete the test?
As for the petty note
: I generally try to avoid to use single line arrow functions for two reasons. The ()
in ({})
easy to forget, which leads to the function not returning anything. And secondly, if you want to add a second line, it's quite tedious to make that happen and I don't see any advantage of using the single line notation in the first place.
That being said, it's personal preference and I'd be open to change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you think it's still got some value let's keep it :)
Same goes for the petty note bits - you've got a solid rational, and it's personal pref vs idle musings.
Keep it all as it is and :)
a357d64
to
80598cb
Compare
WHY are these changes introduced?
Fixes #1419
In every project that uses/renders the Avatar component on server and client, we get a React warning about the initial rendering not being equal.
While mismatches in server-rendered in client-rendered results usually don't seem to be as much of an issue anymore as of react 16, they can be if nodes are missing in the server-rendered output, which I think is precisely the case here.
https://reactjs.org/blog/2017/09/26/react-v16.0.html
Example issue: facebook/react#10591
There's another issue. Unfortunately, it seems like React only ever warns for the first mismatch. In some projects, (almost) all pages contain the Avatar component, and since it always produces an error, we might have been missing others.
WHAT is this pull request doing?
Instead of not rendering the image on the server and rendering it on the client, we now wait for the component to be mounted to render the image. So it won't be part of the server render, but also not part of the initial client side render anymore.
This does cause an addional rerender, but I'd assume that's ok(?)
The change should have no effect on the UX/behavior of the component.
How to 🎩
🖥 Local development instructions
🗒 General tophatting guidelines
📄 Changelog guidelines
Copy-paste this code in
playground/Playground.tsx
:First avatar will fail to load the image and show the initials.
Second avatar loads and shows image.
🎩 checklist
README.md
with documentation changes