DEV Community

Cover image for React Custom Hook: useDarkMode
Sergey Leschev
Sergey Leschev

Posted on

React Custom Hook: useDarkMode

In this article series, we embark on a journey through the realm of custom React hooks, discovering their immense potential for elevating your development projects. Our focus today is on the "useDarkMode" hook, one of the many carefully crafted hooks available in the collection of React custom hooks.

Github: https://github.com/sergeyleschev/react-custom-hooks

import { useEffect } from "react"
import useMediaQuery from "../useMediaQuery/useMediaQuery"
import { useLocalStorage } from "../useStorage/useStorage"

export default function useDarkMode() {
    const [darkMode, setDarkMode] = useLocalStorage("useDarkMode")
    const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)")
    const enabled = darkMode ?? prefersDarkMode

    useEffect(() => {
        document.body.classList.toggle("dark-mode", enabled)
    }, [enabled])

    return [enabled, setDarkMode]
}
Enter fullscreen mode Exit fullscreen mode

This custom hook combines two other handy hooks useMediaQuery and useStorage, to provide a seamless dark mode experience. It automatically detects the user's preferred color scheme and persists the dark mode state in the browser's local storage.

One of the main advantages of "useDarkMode" is its simplicity. With just a few lines of code, you can enable dark mode in your React application. By invoking this hook, you'll receive the current dark mode state and a function to toggle it.

The "useDarkMode" hook dynamically updates the HTML body class to apply the "dark-mode" styling whenever dark mode is enabled. This approach ensures consistency across all components without the need for manual class manipulation.

body.dark-mode {
    background-color: #333;
}
Enter fullscreen mode Exit fullscreen mode

You can use the "useDarkMode" hook in various scenarios. Whether you're building a blog, e-commerce platform, or a content-heavy application, dark mode can enhance the user experience, reduce eye strain, and conserve device battery life. The possibilities are endless, and this custom hook makes it a breeze to implement.

To make it even easier, I've included a simple example component, "DarkModeComponent," that showcases how to use the "useDarkMode" hook. By clicking the "Toggle Dark Mode" button, you can instantly switch between light and dark themes. The button's appearance changes dynamically, reflecting the current mode.

import useDarkMode from "./useDarkMode"
import "./body.css"

export default function DarkModeComponent() {
    const [darkMode, setDarkMode] = useDarkMode()
    return (
        <button
            onClick={() => setDarkMode(prevDarkMode => !prevDarkMode)}
            style={{
                border: `1px solid ${darkMode ? "white" : "black"}`,
                background: "none",
                color: darkMode ? "white" : "black",
            }}
        >
            Toggle Dark Mode
        </button>
    )
}
Enter fullscreen mode Exit fullscreen mode

Throughout this article series, we focused on one of the gems from the collection of React custom hooks – "useDarkMode". This hook, sourced from the "react-custom-hooks" repository, revolutionizes how we work in our React applications.

Full Version | React Custom Hooks:
https://dev.to/sergeyleschev/supercharge-your-react-projects-with-custom-hooks-pl4

Top comments (4)

Collapse
 
sjmulder profile image
Sijmen J. Mulder

Note that browsers have native support for dark mode. To opt in:

<meta name="color-scheme" content="light dark">
Enter fullscreen mode Exit fullscreen mode

Most browsers will trigger a light-on-dark color scheme just by doing this. In CSS you can use media queries, e.g.:

@media (prefers-color-scheme: dark) {
    .some-component { color: white; background-color: #1c1c1c; }
} 
Enter fullscreen mode Exit fullscreen mode

This way your site will automatically adapt to the dark mode setting of the browser or OS.

Collapse
 
sergeyleschev profile image
Sergey Leschev • Edited

Absolutely, Sijmen! You're absolutely right that browsers have integrated support for dark mode. This approach leverages the browser's built-in functionality, and your suggestion provides an excellent alternative for implementing dark mode without relying solely on custom React hooks. But..

Benefits of "useDarkMode" Custom Hook:

  1. Full Control and Customization: With the "useDarkMode" custom hook, you have complete control over the design, color palette, and styling of your dark mode. You can tailor the appearance to match your brand and design intent.
  2. Simplified CSS: The custom hook abstracts the complexity of toggling between light and dark mode styles, reducing the complexity of your CSS codebase.
  3. User-Initiated Toggle: The hook allows users to switch between light and dark modes within your website, independent of their system-wide settings. This can improve user engagement and experience.
  4. Integration with UI Components: You can easily integrate the "useDarkMode" hook into your UI components, allowing for a seamless and unified dark mode experience throughout your application.

Drawbacks of Browser's Built-in Dark Mode:

  1. Limited Customization: Relying solely on browser dark mode settings limits your ability to customize the design and appearance of your dark mode to align with your branding and user experience goals.
  2. Dependency on User Settings: Your website's appearance depends on the user's system-wide dark mode setting. This might not align with your design intent and could lead to a disconnect between your brand and the user experience.
  3. Compatibility Issues: Not all browsers or platforms support the prefers-color-scheme media query, leading to potential compatibility issues and inconsistent behavior.
  4. Limited Accessibility Control: Browser-based dark mode might not provide the accessibility features needed for all users, potentially excluding those with specific visual needs.

"useDarkMode" custom hook offers greater control, customization, consistency, and accessibility over relying solely on the browser's built-in dark mode variant. It empowers you to create a tailored dark mode experience that aligns with your design goals while overcoming the limitations and potential drawbacks associated with browser-native dark mode.

Collapse
 
sjmulder profile image
Sijmen J. Mulder

This reads like LLM-generated content but I will address some of the points:

"Full control" / "Limited customization" - it's just CSS, you can do the same things.

"Limited accessiblity control" - FUD

"Dependency on user settings" / "compatibility issues" - all common browsers support this, but even if not, using media queries gracefully falls back to the defaults. And it's not either/or - you can still provide a setting on your site: e.g. "default/dark/light".

Thread Thread
 
sergeyleschev profile image
Sergey Leschev

Absolutely, CSS customization indeed offers great control, but the value of the "useDarkMode" hook lies in its simplicity and seamless integration. It's more about convenience and providing an easy way to implement dark mode with just a few lines of code. Also, while browser support is strong and fallbacks are available, the hook offers a standardized approach that enhances user experience. It's all about striking a balance between customization and accessibility.