-
Notifications
You must be signed in to change notification settings - Fork 562
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
shouldComponentHydrate #46
Conversation
} | ||
|
||
shouldComponentHydrate() { | ||
return 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.
Can it be a static class property instead?
// Stateful:
class CodeSplittingComponent extends React.Component {
static shouldComponentHydrate = false;
// ...
}
// Stateless:
const CodeSplittingComponent = () => {/* ... */};
CodeSplittingComponent.shouldComponentHydrate = 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.
It could be, but that would make the functionality less flexible. I really enjoy the potential symmetry with the shouldComponentUpdate
lifecycle and was trying to keep usage roughly equivalent (providing a function that returns a boolean based on props.)
Further motivation for this is content that can't be hydrated at the client at all, e.g. when SSR involves significant work or additional data (such as data lookup, localization or large legacy libraries), or the content itselv is too large and sending a duplicate for hydration is prohibitively expensive. |
Note that the current behavior of <div
dangerouslySetInnerHTML={{
__html: ''
}}
suppressHydrationWarning
/> See a working example her: https://codesandbox.io/s/zx38ow3z8x One obvious alternative is to document this behavior and commit to preserving it. |
Seems to be possible to create a component which handles this using the logic from @alexmog2. It would look like this... function ConditionallyHydrate({ shouldHydrate = true, children }) {
if (shouldHydrate) {
return <div>{children}</div>;
}
return (
<div
dangerouslySetInnerHTML={{
__html: ''
}}
suppressHydrationWarning
/>
);
} Working example here: https://codesandbox.io/s/043n21xn1w |
The next step in the RFC process is
It appears that there is a consensus here (of all the people who paid attention so far) that this is a useful performance feature and its implementation is straightforward. What needs to happen for it to become a reality? |
+1 Can help page load performances & eliminate potential FOUC. All for it |
Some guidance from core at this point would be useful as to how such a feature should be implemented. Not sure if it’s standard to tag people though |
<div
dangerouslySetInnerHTML={{
__html: ''
}}
suppressHydrationWarning
/> ^ Very interesting, wasn't aware of What I'm really looking for here is a first-class way to opt out of rehydration, while still allowing the content to potentially change in future render passes. That's the blend of behavior that works best for an SSR->client side async component workflow without unload/load flashing, etc. |
@probablyup The documentation says: "If a single element’s attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the warning by adding suppressHydrationWarning={true} to the element. It only works one level deep, and is intended to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch it up, so it may remain inconsistent until future updates." I believe this is what you're after? |
@jciolek actually yes I think that might work. |
|
I think the innerHTML thing is probably the way to go for now. For anyone looking for the inverse problem where you only want to render something on the client, Partial Hydration will provide a mechanism for that. The server can render a Suspense boundary with a permanent fallback in the HTML. In fact, I think that's probably what the synchronous server renderer will do by default if the server suspends a component. That will cause the client to throw it out and render the content client side. You can kind of do the thing where you leave the HTML in place with partial hydration since it doesn't actually have to hydrate everything to be interactive. You can simply suspend by throwing a Promise that never resolves. The issue is that if any Context above that component changes, we'll throw out the content and trigger the fallback. Because that Context might have changed the HTML. Ultimately, I think we'll want a way to pass rendered content as some kind of JSON object from the server. In a way that can be passed around and just rendered in the tree. Ideally with some embedded child components. <div>{serverStuff}</div> If that was server rendered, maybe that data can simply refer to the HTML that was already sent instead of duplicating the HTML. |
Thanks for the RFC, and sorry for a very late review (#182). Quoting the motivation:
We have a first-class solution to this now, which you can read about here: reactwg/react-18#37. In particular, it allows code splitting to seamlessly work with SSR, and partially hydrate the page as the code loads. There is a demo there that you can play with. There may be other related problems, so there may still be a space for additional related RFCs. But I'll close this one. |
View formatted RFC
This RFC seeks to add the capability for a component subtree to opt out of rehydration diffing.