useIsClient vs useIsMounted
Timing and Purpose
useIsClientspecifically tells you if the code is running in a browser vs server environmentuseIsMountedtells you if a component is currently mounted in the DOM
Implementation
useIsClientusesuseStatedirectly and only sets totrueonceuseIsMountedusesuseRefand returns a callback function that checks the ref
Return Value
useIsClientreturns a boolean directlyuseIsMountedreturns a function that returns a boolean
Here are scenarios where they would differ:
tsx
function Example() { const isClient = useIsClient() const isMounted = useIsMounted()
// Scenario 1: Initial Server-Side Rendering console.log(isClient) // false during SSR, true after hydration console.log(isMounted()) // true in both cases
// Scenario 2: Component Unmounting useEffect(() => { const timer = setTimeout(() => { console.log(isClient) // true (doesn't change) console.log(isMounted()) // false (component unmounted) }, 1000)
return () => clearTimeout(timer) }, [])
return null}Server-Side Rendering
useIsClientwill befalseduring SSR and initial render, thentrueafter hydrationuseIsMountedwill betrueas soon as the component mounts, regardless of SSR
Component Lifecycle
useIsClientstaystrueonce set, even if the component unmountsuseIsMountedbecomesfalsewhen the component unmounts
Race Conditions
useIsClientis better for conditional rendering based on client/server environmentuseIsMountedis better for preventing state updates after unmounting
tsx
// Example where `useIsMounted` is more appropriatefunction DataFetcher() { const isMounted = useIsMounted()
useEffect(() => { fetchData().then((data) => { // Prevents memory leak and updates after unmount if (isMounted()) { setData(data) } }) }, [])}tsx
// Example where `useIsClient` is more appropriatefunction BrowserFeature() { const isClient = useIsClient()
// Only renders browser-specific features after hydration return isClient ? <WindowSizeDisplay /> : null}