Created
October 5, 2023 08:32
-
-
Save OliverJAsh/58af4f7ab5ac6cc7584ef78f16462ba9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
const useIsFirstRender = (): boolean => { | |
const isFirst = React.useRef(true); | |
if (isFirst.current) { | |
isFirst.current = false; | |
return true; | |
} else { | |
return false; | |
} | |
}; | |
/** | |
* Use case: | |
* - A component must be rendered on the server. | |
* - On the client-side, rendering is conditional e.g. based on window width. | |
* - However, in order for hydration to succeed, the first client render must | |
* match the DOM generated from the HTML returned by the server. This means | |
* the component must be rendered again during the first client render and | |
* removed afterwards. | |
* - Hydration is expensive, so we really don't want to pay that penalty only | |
* for the element to be removed immediately afterwards. | |
* | |
* This component conditionally skips hydrating children by removing them from | |
* the DOM _before the first client render_. Removing them before ensures | |
* hydration is successful. | |
*/ | |
export const SkipRenderOnClient: React.FC<{ | |
children: React.ReactNode; | |
shouldRenderOnClient: IO<boolean>; | |
}> = ({ children, shouldRenderOnClient }) => { | |
const id = React.useId(); | |
const isBrowser = typeof window !== 'undefined'; | |
const isFirstRender = useIsFirstRender(); | |
if (isBrowser && isFirstRender && shouldRenderOnClient() === false) { | |
const el = document.getElementById(id); | |
if (el !== null) { | |
el.innerHTML = ''; | |
} | |
} | |
const shouldRender = isBrowser ? shouldRenderOnClient() : true; | |
return <div id={id}>{shouldRender && children}</div>; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment