Implement dark mode in React 🌞🌕
Tags: programming, react, css
Published: 2021-09-18 17:59:04

Who doesn't want a dark theme on their website! Not only does it help us focus better, but also keeps our eyes safer 🤓.

The blog might add value if you belong to either of these situations -

* Maybe you have been in a place wherein you want to implement a dark theme for your website but are struggling around the same 😵. 


* You are starting out with React, so this might just be another fun exercise for you to try 🎉.

## Prerequisites 
* Basic knowledge of React and terminologies (state, props, etc.)
* Basic knowledge of CSS
* Will to learn 🚀

## Spin up a new React Project ✨
You could use your local development environment or maybe use a sandbox. 
>Note📝 - If using local setup prefer cleaning up the factory code before moving further.

Also, I will be using class based components for this one - *not using React Hooks*. 

## Create a simple page
In our `App()`, just return a `div` for the time being. (Can use a `button` as well)

![Init setup](https://gcdn.pbrd.co/images/01QinBSQ0fNs.png?o=1)

## Add state to our app
We cannot do much with a *dumb component* when it comes to embedding logic inside of it. So we need to add `state` to the React component.

Add a state called `isDarkThemeEnabled` to the `App` component and set it to `false`.
![Adding state](https://gcdn.pbrd.co/images/ag3pVgfVXhTE.png?o=1)

## Creating the theme switcher logic 💡
This is the crux of the entire problem. 
> How to build the theme switcher / toggler ?

This might become simple, if you try to draw an analogy to a light bulb. A light bulb has two states `on` and `off`. 
At any given point of time it is in one of the either states.

Now, imagine the theme switcher to be a bulb and try to map the idea.

You got it! 🎉 If the theme switcher is imagined to be a light bulb, `light mode` becomes `on` and `dark mode` becomes `off` or vice-versa.

Now, how to toggle the state ? Pretty simple, just flip the current state whenever a certain event fires.
In simpler terms - on clicking a button change the state value from `true` to `false` or vice versa.

## Implementing the theme switcher logic
Now, as we have designed the approach it's good time to start coding up the idea. 
FYI for changing state in React we use the `setState` function. You can read about the `setState` API from <a href="https://reactjs.org/docs/react-component.html#setstate" target="_blank">here</a>.

Let's create a `clickHandler` and embed the state-toggler logic inside of it. 
![Click handler](https://gcdn.pbrd.co/images/D1Tgr6rNzzYs.png?o=1)

Pass this `clickHandler` to the `onClick` prop of the div, to trigger the function whenever user clicks on the div.

![clickHandler passed to prop](https://gcdn.pbrd.co/images/JRBqnvVocHHr.png?o=1)

## Adding SVG to our app
I want to let the user know which mode he can currently switch to. Can be accomplished with text, but what better than using SVG icons to enhance the UI !🎉

I will be using <a href="https://heroicons.com/" target="_blank">heroicons</a> for high quality SVG icons.

Create two files in your `/src` directory, for two SVG icons for the two states. I will be using a Moon and a Sun SVG in this case.

![folder structure](https://gcdn.pbrd.co/images/5dvXgTl8N2Sb.png?o=1)

To use any SVG in our React app, we can directly use them in our code or import the SVG as a React Component. I prefer the latter as it helps to keep the code cleaner.

This is how we import an SVG icon as a React component - 
```javascript
import {ReactComponent as Moon} from './moon.svg';
```
We need to toggle the SVG icons as well to suit our purpose. For this we will use `conditional rendering`. 
This is a gem 💎. You can read about this <a href="https://reactjs.org/docs/conditional-rendering.html" target="_blank" >here</a>.

The idea is, whenever `isDarkThemeEnabled` is `true` we need the `sun` SVG to show up else the `moon` SVG should show up.

![conditional render](https://gcdn.pbrd.co/images/EHAchyNyzNeh.png?o=1)

This is how the app looks right now. You're almost there.🏁
![demo GIF](https://media.giphy.com/media/YBGzbUgmiLwfZ8btYR/giphy.gif?cid=790b76119a759f7e2e69f43d496b14312912450918b94cdf&rid=giphy.gif&ct=g)

## Let's style up our app 
When `dark mode` is enabled we would want to paint our app background dark. So, for this we would prefer applying `classNames conditionally`.
You can read on this from <a href="https://www.pluralsight.com/guides/applying-classes-conditionally-react" target="_blank">here</a>.

We would be using `JSX expression ` and `Template Literals` for this. When `isDarkThemeEnabled` is set to `true`, which means `dark mode` is enabled, we would append a `className` to the `App` className.

```javascript
className={`App ${isDarkThemeEnabled && "dark-mode"}`}
```

Now lets add some style for the `.App.dark-mode` class.

![CSS for App](https://gcdn.pbrd.co/images/AYcZa5vYeBd1.png?o=1)

Let's also style up the SVG icons 💅. Add a className of `moon` and `sun` to `<Moon />` and `<Sun />` components respectively.

This is how the App code looks right now.

```javascript
import "./styles.css";
import React from "react";
import { ReactComponent as Moon } from "./moon.svg";
import { ReactComponent as Sun } from "./sun.svg";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isDarkThemeEnabled: false,
    };
  }

  handleClick = () => {
    const { isDarkThemeEnabled } = this.state;
    this.setState({
      isDarkThemeEnabled: !isDarkThemeEnabled,
    });
  };

  render() {
    const { isDarkThemeEnabled } = this.state;
    return (
      <div className={`App ${isDarkThemeEnabled && "dark-mode"}`}>
        <div className="toggler-btn" onClick={this.handleClick}>
          {isDarkThemeEnabled ? (
            <Sun className="sun" />
          ) : (
            <Moon className="moon" />
          )}
        </div>
      </div>
    );
  }
}

export default App;

```

Add desired styles in the `styles.css`.
![styles](https://gcdn.pbrd.co/images/EG3sEjQT2J30.png?o=1)

✨ Add a transition time to the wrapper class to make the color switch smoother. I added `transition: 0.3s ease` to `.App`.

This is how the App looks finally!
<strong>Note</strong> - I have added some additional styles and animations.

For a larger websites use `css variables` to make painting UI components on theme toggle easier.

Feel free to play around with the sandbox.

{% codesandbox competent-snowflake-d8ox5 %}

## Conclusion 

<strong>Congratulations!!</strong> 🎉🎉 You made it till the end. If you're still here chances are you probably liked the blog. 

You can also make improvisations to this simple project and share them. This would help in getting the fundamentals stronger 🏋 🚀.

Do let me know how you liked the blog and where I need to improve. Would be eagerly waiting for feedback!