Dark Mode in React using Hooks
Tags: showdev, react, javascript, css
Published: 2020-05-12 21:18:10



### Why need `Dark Mode` ?
Because it looks cool 😎 
Correct but its not enough. Dark mode is known to save a lot of energy on AMOLED screens. Android case studies focused on popular Google apps like YouTube have shown that the power savings can be up to 60%.

Let's see how to implement it in React by using `hooks` and browser's `localStorage`.
We will use here facebook's `react-boilerplate`.
Clone it first by using the command `npx create-react-app dark-mode`, after cloning, change the root directory to `dark-mode` by using `cd dark-mode` and to run the application `npm start`, use this [create-react-app](https://create-react-app.dev) for more details.

{% codesandbox determined-ives-kwc7k %}


### Let's add some darkness 😃

####Create CSS Files

```javascript
// light-theme.css

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

```javascript
// dark-theme.css

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

As of now, I have added only two color variables, later you can add as many color variables for your project.
Don't hardcode color in any css files or in any inline styling, use only defined color variables.
```javascript
// 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);
}
```
I have used those color variables in App.css file.

####Create `DarkModeToggle` component
[click to see the folder structure](https://dev-to-uploads.s3.amazonaws.com/i/mqtxhl22mg6ihkkluni8.png)
Create **DarkMode** folder, add **index.js** and **index.css** files.

```javascript
// DarkMode/index.js

const DarkModeToggle = () => {
  const [isDark, setIsDark] = useState(localStorage.getItem("theme") === "dark" ? true : false);
  useEffect(() => {
    document
    .getElementsByTagName("HTML")[0]
    .setAttribute("data-theme", localStorage.getItem("theme"));
  },[]);
```
Using `useState` hook to store the current user theme preference, get the current user preference from `localStorage`.
Suppose you are running the application for first time, you won't get the user theme preference in browser's `localStorage`, in that case `false` get set to the `isDark` hook and applied `light` theme to the application.
I have used browser's `localStorage` to set the choosen user theme preference and update it while theme toggling.
Set HTML `data-theme` attribute accordingly with current user theme preference.

**Note:** The **data-*** attribute is used to store custom data private to the page or application. The **data-*** attribute gives us the ability to embed custom data attributes on all HTML elements.

```javascript
// handles user theme preference change

const toggleThemeChange = () => {
    if (isDark === false) {
      localStorage.setItem("theme", "dark");
      document
        .getElementsByTagName("HTML")[0]
        .setAttribute("data-theme", localStorage.getItem("theme"));
        setIsDark(true);
    } else {
      localStorage.setItem("theme", "light");
      document
        .getElementsByTagName("HTML")[0]
        .setAttribute("data-theme", localStorage.getItem("theme"));
        setIsDark(false);
    }
  }
```
This method will get triggered when we toggle the theme from light to dark or vice-versa. It will update the state `isDark` based on current theme choosen and simultaneously update the `data-theme` attribute. `data-theme` attribute helps application to determine which color schemes need to applied either **dark** `html[data-theme="dark"]` or **light** `html[data-theme="light"]`.


```javascript
// templete for theme toggle button

  return (
    <label className="switch">
      <input
        type="checkbox"
        defaultChecked={isDark}
        onChange={() => toggleThemeChange()}
      />
      <span className="slider round" />
    </label>
  )
```
returning the html **toggle** element for switching the theme.
```javascript 
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          <DarkModeToggle />
        </a>
      </header>
    </div>
  );
}
```
Add this `DarkModeToggle` component wherever you want to place it.

###Let's checkout the application after the Darkness applied

{% codesandbox flamboyant-stallman-lh9xw %}

GitHub repo [link](https://github.com/Rohit1508/React-Dark-Mode-Hooks) in case if you want to directly fork it for your project.