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; }> = ({ 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
{shouldRender && children}
; };