useIsClient
Returns false while the page is rendered on the server and during hydration, then true once the component has mounted in the browser.
import { useIsClient } from '@salla.sa/twilight-theme-engine/hooks';In plain words
A storefront page is built twice. First the server runs your components and sends finished HTML (server-side rendering, SSR). Then the browser runs the same components again and attaches itself to that HTML (hydration). Both runs must produce the same result.
Things like the window size, localStorage or the Salla SDK exist only in the browser. useIsClient() is false in both of those first runs and becomes true right after, so you can show browser-only values without the two runs disagreeing.
Signature
function useIsClient(): boolean
Try it live
isClient: false
Window width: …
Browser language: …
import { useIsClient } from '@salla.sa/twilight-theme-engine/hooks';
export function WindowWidth() {
const isClient = useIsClient();
// Never branch on `typeof window` in render: the server and the first browser render must match.
return <span>{isClient ? window.innerWidth : '…'}</span>;
}
Example
import { useIsClient } from '@salla.sa/twilight-theme-engine/hooks';
export function RecentlyViewed() {
const isClient = useIsClient();
if (!isClient) return null; // the server has no localStorage
const ids = JSON.parse(localStorage.getItem('recently-viewed') ?? '[]') as number[];
return <p>You viewed {ids.length} products recently.</p>;
}
How it behaves
It is
useState(false)plus an effect that setstrue, so every component that calls it renders one extra time after mounting.HookSlotuses it to add the<salla-hook>element only after hydration.It has no subpath of its own: import it from
@salla.sa/twilight-theme-engine/hooks.
Gotchas
Branching on
typeof window !== 'undefined'inside render gives the server and the first browser render different output, and React reports a hydration mismatch. UseuseIsClient()(or an effect) instead.Content behind
isClientis missing from the server HTML, so search engines and the first paint do not see it, and the layout can shift when it appears. Reserve its space or keep essential content server-rendered.
Related
Source and docs
- Engine source:
packages/theme-engine/src/hooks/useIsClient.ts