useIsClient
React hook that determines if the code is running on the client side (in the browser) for conditional rendering and SSR compatibility.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/use-is-client.json
npx shadcn@latest add https://www.shadcn.io/registry/use-is-client.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-is-client.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-is-client.json
Features
- SSR compatible - Prevents hydration mismatches in server-side rendered apps
- Simple API - Returns a boolean indicating client vs server execution
- Hydration safe - Starts as
false
, becomestrue
after client hydration - Zero dependencies - Lightweight hook using only React primitives
- Performance optimized - Uses useEffect to detect client-side execution
Usage
import { useIsClient } from "@/hooks/use-is-client"
function MyComponent() {
const isClient = useIsClient()
return (
<div>
{isClient ? (
<p>This renders on the client</p>
) : (
<p>This renders on the server</p>
)}
</div>
)
}
API Reference
useIsClient
useIsClient(): boolean
Returns a boolean value indicating whether the code is running on the client side.
- Returns:
boolean
false
- Code is running on the server or before hydrationtrue
- Code is running on the client after hydration
Usage Examples
Conditional Browser API Access
function BrowserAPIComponent() {
const isClient = useIsClient()
return (
<div>
{isClient ? (
<p>Window width: {window.innerWidth}px</p>
) : (
<p>Window width: Not available on server</p>
)}
</div>
)
}
Preventing Hydration Mismatches
function RandomComponent() {
const isClient = useIsClient()
// This prevents hydration mismatches since Math.random()
// would produce different values on server vs client
if (!isClient) {
return <div>Loading...</div>
}
return <div>Random number: {Math.random()}</div>
}
Client-Only Components
function ClientOnlyFeature() {
const isClient = useIsClient()
if (!isClient) {
return <div className="h-32 bg-muted animate-pulse" />
}
return (
<div>
<p>Current URL: {window.location.href}</p>
<p>User Agent: {navigator.userAgent}</p>
<p>Online: {navigator.onLine ? "Yes" : "No"}</p>
</div>
)
}
Conditional Script Loading
function AnalyticsWrapper() {
const isClient = useIsClient()
useEffect(() => {
if (isClient) {
// Safe to load analytics scripts on client
loadAnalytics()
}
}, [isClient])
return <div>Content with analytics</div>
}
Local Storage Access
function UserPreferences() {
const isClient = useIsClient()
const [theme, setTheme] = useState('light')
useEffect(() => {
if (isClient) {
const savedTheme = localStorage.getItem('theme') || 'light'
setTheme(savedTheme)
}
}, [isClient])
const handleThemeChange = (newTheme: string) => {
setTheme(newTheme)
if (isClient) {
localStorage.setItem('theme', newTheme)
}
}
return (
<div>
<p>Current theme: {theme}</p>
<button onClick={() => handleThemeChange('dark')}>
Dark Theme
</button>
</div>
)
}
Media Query Fallbacks
function ResponsiveComponent() {
const isClient = useIsClient()
const [isMobile, setIsMobile] = useState(false)
useEffect(() => {
if (isClient) {
const checkMobile = () => {
setIsMobile(window.innerWidth < 768)
}
checkMobile()
window.addEventListener('resize', checkMobile)
return () => window.removeEventListener('resize', checkMobile)
}
}, [isClient])
if (!isClient) {
// Render a safe default during SSR
return <div className="desktop-layout">Content</div>
}
return (
<div className={isMobile ? "mobile-layout" : "desktop-layout"}>
Content
</div>
)
}
Common Use Cases
- Browser API access - Safely use window, document, navigator objects
- Preventing hydration mismatches - Avoid server/client render differences
- Client-only features - Geolocation, clipboard, notifications
- Local storage operations - Read/write browser storage safely
- Third-party scripts - Load analytics, ads, or other client-only scripts
- Media queries - Handle responsive behavior with JavaScript
- Random values - Generate client-side random content safely
- Time-sensitive content - Display current time without hydration issues
Implementation Details
- Starts with
isClient: false
to match server-side rendering - Uses
useEffect
to setisClient: true
after component mounts useEffect
only runs on the client, never on the server- Prevents hydration mismatches by ensuring consistent initial render
- Minimal performance impact - only one state update after mount
- Works with all React frameworks (Next.js, Remix, Gatsby, etc.)
Best Practices
- Use for browser APIs: Always wrap browser-specific code with this hook
- Provide fallbacks: Show loading states or safe defaults during SSR
- Avoid overuse: Only use when necessary to prevent unnecessary client-only rendering
- Combine with Suspense: Use with React Suspense for better loading experiences
- Cache results: Consider memoizing expensive client-only computations
useInterval
React hook for managing setInterval with automatic cleanup and pause/resume functionality. Perfect for React applications requiring periodic updates with Next.js integration and TypeScript support.
useIsMounted
Prevent memory leaks by checking component mount state before async operations. Perfect for React applications requiring safe state updates with Next.js integration and TypeScript support.