React useDarkMode Hook
React useDarkMode hook with OS preference sync and localStorage persistence. Dark mode management with TypeScript support for Next.js applications.
Theme Switching Broken?
Join our Discord community for help from other developers.
Ever tried implementing dark mode and realized you need to handle OS preferences, localStorage sync, SSR hydration, class toggling, and media query listeners? You know the drill—check prefers-color-scheme, manage localStorage, prevent flash of wrong theme, handle SSR mismatches. This free open source React useDarkMode custom hook handles all that dark mode complexity so you can focus on your UI instead of fighting with theme persistence bugs in your React applications.
useDarkMode showcase
Complete dark mode management with OS sync:
This free open source React hook simplifies theme switching with TypeScript support for modern JavaScript applications. Whether you're building dashboards, documentation sites, or apps in your Next.js projects, this React hook keeps your dark mode implementation bulletproof.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/use-dark-mode.json
npx shadcn@latest add https://www.shadcn.io/registry/use-dark-mode.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-dark-mode.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-dark-mode.json
Why most dark mode implementations suck
Look, you could manually check window.matchMedia, add event listeners, manage localStorage, toggle classes, and handle SSR edge cases. But after debugging the third "flash of wrong theme" bug, you'll appreciate having this handled properly.
Most developers forget about the flash of unstyled content (FOUC) in React applications. Or they ignore SSR hydration mismatches that break Next.js builds. Some handle OS preference detection but forget localStorage persistence, losing user choices on refresh.
The React hook automatically syncs with OS preferences—when users change their system theme, your app follows in TypeScript components. It persists their choice to localStorage so it remembers across sessions. Plus it handles the SSR nightmare of hydration mismatches in Next.js projects.
Real talk—dark mode seems simple until you hit the edge cases in JavaScript applications. Flash of unstyled content, SSR mismatches, OS preference changes, localStorage failures. This React hook handles all of it.
This free open source React hook handles the theme boilerplate while you focus on building features. Whether you're creating React applications, Next.js projects, or TypeScript codebases, this custom hook keeps your dark mode rock solid.
Features
- OS preference detection with automatic synchronization to system theme in React applications
- localStorage persistence for user preference across sessions with error handling for TypeScript components
- SSR-safe initialization with hydration mismatch prevention for Next.js projects
- TypeScript support with complete type definitions and IntelliSense integration
- Automatic DOM updates applying dark class to document root in JavaScript applications
- shadcn/ui integration with Tailwind CSS dark mode support for React development
- Free open source designed for modern React development workflows
When you'll actually use this
Real talk—this isn't for simple CSS-only dark mode in React applications. If you just need dark styles, use CSS media queries. But when you need user control, persistence, and JavaScript-driven theming, this React hook shines in Next.js projects.
Perfect for:
- Theme switching - User-controlled dark/light mode toggles built with TypeScript
- OS sync - Respecting and reacting to system preference changes in React components
- Persistent themes - Saving user choice across browser sessions using JavaScript storage
- SSR applications - Server-side rendering without hydration mismatches in Next.js applications
- Documentation sites - Reader-friendly theme options with TypeScript integration
- Dashboards - Professional apps with theme preferences in React development
- E-commerce - Accessible shopping experiences with theme control using React patterns
- Content platforms - Reading modes for different lighting conditions in JavaScript applications
API Reference
useDarkMode
Option | Type | Default | Description |
---|---|---|---|
defaultValue | boolean | false | Initial dark mode state |
localStorageKey | string | "usehooks-ts-dark-mode" | localStorage key for persistence |
initializeWithValue | boolean | true | Whether to read from localStorage on mount |
applyDarkClass | boolean | true | Whether to apply dark class to document root |
Return Value
Property | Type | Description |
---|---|---|
isDarkMode | boolean | Current dark mode state |
toggle | () => void | Toggle between dark and light |
enable | () => void | Enable dark mode |
disable | () => void | Disable dark mode |
set | (value: boolean) => void | Set specific mode |
Common gotchas
Flash of wrong theme (FOUC) on load: The React hook tries to prevent this, but if you're not using SSR correctly or loading the hook late in React applications, you might see a flash. Initialize early in your Next.js app structure.
SSR hydration mismatches break builds: Set initializeWithValue: false
for SSR to avoid hydration errors in TypeScript projects. The theme will apply after mount, which is a trade-off but prevents build failures.
localStorage can silently fail: Private browsing, storage quota, or browser settings can block localStorage in JavaScript applications. The hook handles this gracefully but won't persist across sessions.
Root class placement matters: The dark
class goes on <html>
or <body>
, not individual components in React development. This is how Tailwind's dark mode works—make sure your CSS expects this.
Live OS preference updates: When users change their system theme, the React hook updates immediately in TypeScript components. This might surprise users who manually selected a different theme.
Performance impact with many components: Each theme change re-renders components using theme context in Next.js projects. Consider memoization for expensive theme-dependent computations.
Related hooks you will also like
useBoolean
Boolean state management similar to dark mode toggle functionality
useToggle
Advanced toggle state management with custom values
useLocalStorage
localStorage state management with automatic JSON serialization
useMediaQuery
Responsive design with CSS media query detection
useTernaryDarkMode
Three-state dark mode with system, light, and dark options
useIsClient
Client-side rendering detection for SSR-safe theme application
Questions you might have
React useCounter Hook
React useCounter hook for numeric state management. Increment, decrement, and reset controls with TypeScript support for Next.js applications.
React DebounceCallback Hook
React useDebounceCallback hook for debouncing function calls. Control API requests and expensive operations with TypeScript support for Next.js apps.