Switching Light and Dark in React with Chakra UI’s useColorMode Hook
Learn how Chakra UI’s useColorMode hook lets you toggle light and dark themes in React apps. The article covers setup, a working button example, persistence via localStorage, and trade‑offs for production use.
08 Apr 2026, 16:34 UTC

Why You Need a Robust Theme Switcher
Modern web apps often let users toggle between light and dark styles. A good implementation keeps the UI consistent, remembers the choice, and avoids fragile global state. Chakra UI offers a built‑in solution: useColorMode. It’s a simple hook that returns the current mode and a toggling function, backed by a colorModeManager that defaults to localStorage. This article walks through setting it up, using it in components, and understanding its trade‑offs.
1. The useColorMode API at a Glance
The hook signature is:
const [colorMode, setColorMode] = useColorMode();
colorModeis a string:'light'or'dark'.- Calling
setColorModewith a mode string ortoggleColorMode()flips between them. - It automatically updates any component that uses Chakra’s
colorModetheme tokens.
Because the hook reads from the colorModeManager defined in ChakraProvider, the choice persists across page reloads.
2. Wiring the Provider in Your App
Wrap your root component with <ChakraProvider> and optionally supply a custom colorModeManager.
import { ChakraProvider, extendTheme } from "@chakra-ui/react";
const theme = extendTheme({
config: {
initialColorMode: "light",
useSystemColorMode: false,
},
});
function App() {
return (
);
}
By default, Chakra uses localStorage under the key _chakra-ui-color-mode. If you prefer cookies or a custom store, pass a colorModeManager object with get and methods.
3. A Worked Example: A Theme Toggle Button
Below is a minimal component that toggles the theme and shows the current mode. Place this inside any part of the tree that’s wrapped by ChakraProvider.
import { Button, useColorMode, useColorModeValue } from "@chakra-ui/react";
export function ThemeSwitcher() {
const { colorMode, setColorMode } = useColorMode();
const opposite = colorMode === "light" ? "dark" : "light";
return (
<Button onClick={() => setColorMode(opposite)}>
Switch to {opposite} mode
</Button>
);
}
Because all Chakra components reference the colorMode token, the UI updates instantly. To style elements differently per mode, use useColorModeValue:
const bg = useColorModeValue("gray.100", "gray.900");
This returns gray.100 when in light mode and gray.900 in dark mode.
4. Trade‑offs & Limitations
| Aspect | Consideration |
|---|---|
| Persistence | Relies on localStorage by default; cross‑origin scripts can read it unless sandboxed. |
| Performance | Each toggle triggers a re‑render of components consuming color mode tokens. Debounce if toggling rapidly in a high‑frequency UI. |
| Server‑Side Rendering | On the server, localStorage is unavailable; the initial mode falls back to initialColorMode or system preference. |
| Sync with User Profile | Use useEffect to write the mode to a backend when it changes, and preload it via colorModeManager.get() during server render. |
For most client‑side apps, the defaults work out of the box. If you need stricter privacy or complex sync logic, implement a custom colorModeManager.
5. Actionable Checklist
- Wrap your app with
ChakraProviderand setinitialColorMode. - Use
useColorModein a component to toggle the mode. - Replace hard‑coded colors with
useColorModeValueor theme tokens. - Verify persistence: toggle, reload, and confirm
localStorage.getItem('_chakra-ui-color-mode')matches. - If you need server‑side rendering, provide a fallback
colorModeManagerthat reads from cookies. - Consider debouncing the toggle if the button is exposed to rapid user interaction.
With these steps, your React app will support a smooth, persistent light/dark experience using Chakra UI’s lightweight, hook‑based system.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.