Join our Discord Community

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:

Loading component...

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

OptionTypeDefaultDescription
defaultValuebooleanfalseInitial dark mode state
localStorageKeystring"usehooks-ts-dark-mode"localStorage key for persistence
initializeWithValuebooleantrueWhether to read from localStorage on mount
applyDarkClassbooleantrueWhether to apply dark class to document root

Return Value

PropertyTypeDescription
isDarkModebooleanCurrent dark mode state
toggle() => voidToggle between dark and light
enable() => voidEnable dark mode
disable() => voidDisable dark mode
set(value: boolean) => voidSet 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.

Questions you might have