Skip to content

Instantly share code, notes, and snippets.

@OliverJAsh
Created October 5, 2023 08:32
Show Gist options
  • Save OliverJAsh/58af4f7ab5ac6cc7584ef78f16462ba9 to your computer and use it in GitHub Desktop.
Save OliverJAsh/58af4f7ab5ac6cc7584ef78f16462ba9 to your computer and use it in GitHub Desktop.
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