How to do Dark Mode with React Hooks
Tags: react, webdev, javascript, css
Published: 2020-12-29 17:52:31

---
tags:
- React
- WebDev
- JavaScript
- CSS
published: true
description: A simple starter for modular dark mode implementation with React Hooks
title: How to do Dark Mode with React Hooks
cover_image: https://vivaldi.com/wp-content/uploads/Is-dark-mode-better-for-you-980x551.png
---

**Dark Mode** is one of the latest features being widely adopted across apps and websites. Dark colours can prolong the battery life of mobile devices. The savings, according to [Google](https://www.youtube.com/watch?time_continue=64&v=N_6sPd0Jd3g) with the Dark Mode offered on the YouTube app, allows a 15 percent energy reduction at 50 percent brightness and a huge 60 percent reduction at 100 percent bightness. [Apple](https://9to5mac.com/2019/01/22/apple-oled-iphone-2020/) confirmed moving forward in 2020, their phones will feature OLED screens. 

Check out the completed demo [here](https://react-hooks-dark-mode-example.netlify.app/). The completed code for this demo can be found [here](https://github.com/joefstack/react-hooks-dark-mode).

## Why React Hooks

We know with React components allows top-down data flow that helps us organize an application into small manageable pieces of UI. However, with only the component model, components become large and difficult to refactor. In addition, logic may need to be duplicated between components. Hooks are great because they allow us to organize logic within a component into discreet units that are easy to reuse.

> However, we often can’t break complex components down any further because the logic is stateful and can’t be extracted to a function or another component. - [Dan Abramov](https://dev.to/dan_abramov/making-sense-of-react-hooks-2eib)

## Implementing Hooks

For simplicity in demonstrating how to implement **React Hooks** with **Dark Mode**,  we will be using **localStorage** so the browser will remember our user's preference upon reload. In more complex web applications, the user's preference can be stored in a database. So let's begin with Facebook's standard React boilerplate. Clone the repo, change directory into the newly created project folder, and run the application. For more information, check out the [docs](https://create-react-app.dev/).

```
npx create-react-app dark-mode;
cd dark-mode;
npm start;
```

Next, let's add our CSS colour variables. We can start with just a colour and a background colour, but you can add more if you would like to build out a larger colour scheme. This way, we are modularizing our colour styling in a consistent way that can be easily implemented across our site.

```
// App.css

...

html[data-theme="light"]  {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
}

html[data-theme="dark"]  {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
}

...

```

To set the variables, replace the header **CSS** in the **App.css** file like so:

```
// App.css

...

.App-header {
  background-color:var(--background-color);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color:var(--color);
}

...

```

## Creating theme-toggle component

Create a new file in the **src* folder and name it **ThemeToggle**, or something to that effect. This is currently a starter project, if you like, you can create a separate **ThemeToggle** directory. Here, we are going to 'use' the **useState** hook to store the current theme preference.

```
// ThemeToggle.js

...

  const ThemeToggle = () => {
    const [darkMode, setDarkMode] = useState(
      localStorage.getItem("theme") === "dark" ? true : false
    );
    useEffect(() => {
      document
        .getElementsByTagName("HTML")[0]
        .setAttribute("data-theme", localStorage.getItem("theme"));
    }, []);
  };

...

```
If a user is accessing the site for the first time, there will not be a preference set in the **localStorage**. Our **Strict Equality Comparison** operator will throw **false** and the **darkMode** hook to apply the light theme across the application.

This is done using the HTML **data-** [attribute](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes), which allows us to store information in semantic HTML elements. We will use it in the method that is going to be triggered to switch the theme to dark, or vice-versa. Using the same logic, we can also call our **setDarkMode** hook from earlier to set the theme in **localStorage**.

```
// ThemeToggle.js

...

  const switchThemes = () => {
    if (isDark === false) {
      localStorage.setItem("theme", "dark");
      document
        .getElementsByTagName("HTML")[0]
        .setAttribute("data-theme", localStorage.getItem("theme"));
      setDarkMode(true);
    } else {
      localStorage.setItem("theme", "light");
      document
        .getElementsByTagName("HTML")[0]
        .setAttribute("data-theme", localStorage.getItem("theme"));
      setDarkMode(false);
    }
  };

...

```

The last thing we need to do in **ThemeToggle** is return the button to be imported.

```
// ThemeToggle.js

...

  return (
    <label className="switch">
      <input
        type="checkbox"
        defaultChecked={isDark}
        onChange={() => toggleThemeChange()}
      />
      <span className="slider round" />
    </label>
  );

...

```
Now, to test, we can import it into our **App.js**.

```
// App.js

...

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          React Hooks Dark Mode Starter
        </p>
        <ThemeToggle />
      </header>
    </div>
  );
}

...

```

## Congratulations!!

Now, you have a usable element that can place wherever you want in your application. If you want to take a look at the complete code, or create your own fork, check out my repo [here](https://github.com/joefstack/react-hooks-dark-mode).

Originally published at [https://www.josephc.how/react-hooks-dark-mode/](https://www.josephc.how/react-hooks-dark-mode/)