useIsClient vs useIsMounted
:::tip
useIsClient is primarily for handling SSR scenarios, while useIsMounted is for managing component lifecycle and preventing memory leaks or updates after unmounting.
:::
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:
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
// Example where `useIsMounted` is more appropriate
function DataFetcher() {
const isMounted = useIsMounted()
useEffect(() => {
fetchData().then((data) => {
// Prevents memory leak and updates after unmount
if (isMounted()) {
setData(data)
}
})
}, [])
}
// Example where `useIsClient` is more appropriate
function BrowserFeature() {
const isClient = useIsClient()
// Only renders browser-specific features after hydration
return isClient ? <WindowSizeDisplay /> : null
}