A performant, SSR-safe React hook for tracking media queries using useSyncExternalStore. Optimized for Next.js and React 18+ with support for legacy browsers.
Perfect for simple responsive logic in client components.
import { useMediaQuery } from '@barso/hooks';
function SimpleComponent() {
const isMobile = useMediaQuery('(max-width: 768px)');
return <div>{isMobile ? 'Viewing on Mobile' : 'Viewing on Desktop'}</div>;
}- ⚡ React 18 Ready: Uses
useSyncExternalStoreto prevent "tearing" and ensure consistency. - 🌐 SSR/Next.js Compatible: Handles hydration gracefully with customizable fallbacks.
- ⏱️ Built-in Debounce: Optional delay to prevent excessive re-renders during window resizing.
- 🔄 Legacy Support: Automatic fallback for browsers not supporting
addEventListeneronmatchMedia. - 🎣 Event Callback: Integrated
onChangelistener for side effects.
To prevent Flash of Unstyled Content (FOUC) or layout shifts in Next.js, you can sync the server-side state (derived from cookies or user-agent) with the hook using the fallback option.
// app/page.js (Server Component)
import { cookies } from 'next/headers';
import ThemeWrapper from './ThemeWrapper';
export default function Page() {
// Read the saved theme from cookies to ensure the server renders the correct UI
const themeCookie = cookies().get('theme')?.value;
const isDarkMode = themeCookie === 'dark';
return <ThemeWrapper initialIsDark={isDarkMode} />;
}
// ThemeWrapper.js (Client Component)
'use client';
import { useMediaQuery } from '@barso/hooks';
export default function ThemeWrapper({ initialIsDark }) {
const isDark = useMediaQuery('(prefers-color-scheme: dark)', {
// Use the server-provided state during hydration
fallback: initialIsDark,
// Optional: add debounce for smoother transitions
debounceMs: 200,
onChange: (matches) => {
console.log('Theme changed to:', matches ? 'dark' : 'light');
}
});
return (
<div className={isDark ? 'dark-mode' : 'light-mode'}>
<h1>Themed Content</h1>
</div>
);
}| Argument | Type | Description |
|---|---|---|
query |
string |
The media query to track (e.g., (min-width: 1024px)). |
options |
object |
Configuration object. |
| Property | Type | Default | Description |
|---|---|---|---|
debounceMs |
number |
undefined |
Delay in ms to wait before updating the state. |
fallback |
boolean | () => boolean |
false |
Initial value used on server and during hydration. |
onChange |
(matches: boolean) => void |
undefined |
Callback function triggered on every change. |