How to Utilize Dark Mode in React Application?

Light/dark mode is a popular feature in modern web applications that allows users to switch between a light and a dark colour scheme. Implementing this feature can improve the user experience by giving users the ability to choose a colour scheme that is most comfortable for them to use. In addition, light/dark mode can also improve the accessibility of an application by providing high-contrast options for users with visual impairments.

In this tutorial, we will learn how to implement light/dark mode in a React application. We will start by setting up a new React project and installing the necessary dependencies. Then, we will create a toggle button to switch between light and dark modes and use React state to store the current mode. We will also learn how to persist the user’s mode preference using local storage and enhance the user experience by adding a transition effect and allowing the user to set their preferred mode in the application’s settings.

Here you can see the Live Demo!

Before getting started, make sure you have the latest version of Node.js and npm installed on your machine. You can check your current version by running the following command in your terminal:

node -v
npm -v

With the prerequisites out of the way, let’s get started!

Setting up a React project:

Before we start implementing the light and dark theme in our React application, we need to set up a new React project and install the required libraries and dependencies.

Prerequisites:

  • Node.js: Make sure you have Node.js installed on your system. You can download the latest version of Node.js from the official website (https://nodejs.org/)
  • npm: npm (short for Node Package Manager) is a package manager for JavaScript, and it is included with Node.js. You can check if you have npm installed by running the following command in the terminal:
    npm -v

Setting up a new React project:

We will use the create-react-app command to set up a new React project. Open the terminal and navigate to the directory where you want to create the project. Then, run the following command:

npx create-react-app light-dark-app

Replace “my-app” with the desired name for your project. This will create a new React project with the specified name and install all the required dependencies.

Importing the required libraries and dependencies:

To create a light and dark theme in our React application, we will need to import the following libraries and dependencies:

  • styled-components: styled-components is a library for styling React components. It allows you to write CSS styles in your JavaScript code and apply them to your components. It provides a powerful and flexible way to style your components, and it also makes it easy to manage your application’s design system. With styled-components, you can write your styles as a template literal, which is a string that is enclosed in backticks () and can span multiple lines. You can then use this template literal to create a styled component by calling the styled` function and passing in the component that you want to style as an argument.

To install styled-components, run the following command in the terminal:

npm install styled-components

With the dependencies installed, we can now set up the project structure. Create a new directory called “components” in the “src” directory. Inside the “components” directory, create a new file called “Toggle.js” and a new directory called “styles”. Inside the “styles” directory, create a new file called “globalStyles.js”. Your project structure should now look like this:

light-dark-app
├── src
│   ├── components
│   │   ├── App.js
│   │   └── styles
│   │       └── globalStyles.js
│   └── index.js
└── package.json

With the project set up, we can now move on to implementing the light/dark mode toggle.

Implementing the light/dark mode toggle:

In this section, we will implement a toggle button that allows the user to switch between light and dark mode in a React application.

First, let’s add a toggle button to our React application. Open the “App.js” file and add the following code:

import logo from "../logo.svg";
import "../App.css";
import React from "react";

const App = ({ mode, onToggle }) => {
  return (
    <div className="App">
      <img src={logo} className="App-logo" alt="logo" />
      <h1>Light or dark mode?</h1>
      <button onClick={() => {
      onToggle(mode === 'light' ? 'dark' : 'light');
    }}>
      Toggle {mode === 'light' ? 'dark' : 'light'} mode
    </button>
    </div>
  );
};

export default App;

This code defines a new React component called “App” that displays a button with the text “Toggle dark mode” if the current mode is “light”, or “Toggle light mode” if the current mode is “dark”. When the button is clicked, the component will call the onToggle function and pass in the new mode.

To make the change in a mode more visually appealing, let’s add a transition effect when switching between modes. To do this, we will use the styled-components library to define a transition on the body element.

Now, create a new file called “globalStyles.js” and add the following code:

import { createGlobalStyle } from 'styled-components';

const GlobalStyles = createGlobalStyle`
  body {
    transition: background-color 0.5s ease-out, color 0.5s ease-out;
    background-color: ${props => (props.mode === 'light' ? 'white' : 'black')};
    color: ${props => (props.mode === 'light' ? 'black' : 'white')};
  }
`;

export default GlobalStyles;

This code defines a new global style that adds a transition effect to the background-color and color properties of the body element. The style also uses the mode prop to set the appropriate colours for each mode.

To apply these styles to our application, we will need to import the “GlobalStyles” component and render it in the “index.js” file. Update the “index.js” file with the following code:

Next, let’s update the “index.js” file to render the “App” component and pass in the current mode and the handleToggle function as props. Replace the contents of the “index.js” file with the following code:

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import GlobalStyles from './components/styles/globalStyles';

const Root = () => {
  const [mode, setMode] = useState(null);

  useEffect(() => {
    const storedMode = localStorage.getItem('mode');
    if (storedMode) {
      setMode(storedMode);
    } else {
      setMode('light');
    }
  }, []);

  const handleToggle = newMode => {
    setMode(newMode);
    localStorage.setItem('mode', newMode);
  };

  return (
    <>
      {mode && <GlobalStyles mode={mode} />}
      <App mode={mode} onToggle={handleToggle} />
    </>
  );
};

ReactDOM.render(
  <Root />,
  document.getElementById('root')
);

Now if you run the application, you should see the background and text colours change smoothly when you click the toggle button.

With the light/dark mode toggle working, let’s move on to the next step: persisting the user’s mode preference using local storage.

Persisting the user’s mode preference:

To save the user’s mode preference in local storage, we can use the localStorage API. Open the “App.js” file and update the handleToggle function to save the current mode to local storage:

const App = ({ mode, onToggle }) => {
  return (
    <button onClick={() => {
      const newMode = mode === 'light' ? 'dark' : 'light';
      onToggle(newMode);
      localStorage.setItem('mode', newMode);
    }}>
      Toggle {mode === 'light' ? 'dark' : 'light'} mode
    </button>
  );
};

With the mode preference being saved to local storage, we can now retrieve it on page load and use it to set the initial mode of the application. To do this, we will update the “index.js” file to retrieve the user’s preference from local storage when the component mounts.

Update the “index.js” file with the following code:

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import GlobalStyles from './components/styles/globalStyles';

const Root = () => {
  const [mode, setMode] = useState(null);

  useEffect(() => {
    const storedMode = localStorage.getItem('mode');
    if (storedMode) {
      setMode(storedMode);
    } else {
      setMode('light');
    }
  }, []);

  const handleToggle = newMode => {
    setMode(newMode);
    localStorage.setItem('mode', newMode);
  };

  return (
    <>
      {mode && <GlobalStyles mode={mode} />}
      <App mode={mode} onToggle={handleToggle} />
    </>
  );
};

ReactDOM.render(
  <Root />,
  document.getElementById('root')
);

With these changes, the application will now retrieve the user’s preferred mode from local storage when it loads, and the mode will be persisted between page reloads.

And that’s it! You now have a fully functional light/dark mode toggle in your React application. You can customize the style and behaviour of the toggle to suit your needs, and use it to provide a more personalized and accessible user experience for your users.

Adding Style:

Now as the functional part is over, we can focus on styling the page and the button. So let’s style the page.

In this section, we will customize the appearance of the light/dark mode toggle using CSS styles.

First, let’s update the toggle button to use a switch style instead of a plain button. To do this, we will use an HTML checkbox input and a label element, and apply styles to them using CSS.

Open the “App.js” file and update the component to use the checkbox input and label element:

import logo from "../sitelogo.svg";
import logo2 from "../siteicon.svg";

import "../App.css";
import React from "react";

const App = ({ mode, onToggle }) => {
  const siteIcon = mode === "light" ? logo : logo2;

  return (
    <div className="App">
      
      <img src={siteIcon} className="App-logo" alt="logo" />
      <h1>Light/Dark Mode</h1>
        <input type="checkbox" id="switch" /><label  onClick={() => {
          onToggle(mode === "light" ? "dark" : "light");
        }} for="switch">
        Toggle {mode === "light" ? "dark" : "light"} mode
        </label>
    </div>
  );
};

export default App;

As you can see we’ve used two SVG icons, where one’s colour is white and another is black in colour. We’re basically changing the logo while changing the background colour.

Now, we’ll add CSS to the input and the label tags.

input[type=checkbox]{
	height: 0;
	width: 0;
	visibility: hidden;
}

label {
	cursor: pointer;
	text-indent: -9999px;
	width: 200px;
	height: 100px;
	background: grey;
	display: block;
	border-radius: 100px;
	position: relative;
}

label:after {
	content: '';
	position: absolute;
	top: 5px;
	left: 5px;
	width: 90px;
	height: 90px;
	background: #fff;
	border-radius: 90px;
	transition: 0.3s;
}

input:checked + label {
	background: #3f48f5;
}

input:checked + label:after {
	left: calc(100% - 5px);
	transform: translateX(-100%);
}

label:active:after {
	width: 130px;
}

These CSS styles customize the appearance of the checkbox input and label element to create a switch style toggle. The checkbox input is hidden and the label element is styled to display a grey toggle with a white switch. The label element also has an ::after pseudo-element that is styled to display a white circle that moves horizontally when the toggle is clicked. The toggle background color changes to blue when the toggle is checked, and the switch animates to the other side of the toggle. The styles also include a cursor style for the label element and a transition effect for the ::after pseudo-element to create a smooth animation when the toggle is clicked.

Conclusion:

In this article, we learned how to implement light/dark mode in a React application using the styled-components library. We saw how to create a toggle button that allows the user to switch between the two modes, and how to update the styles of the application based on the current mode. We also learned how to persist the user’s mode preference using the localStorage API.

Implementing light/dark mode in a React application can be a useful way to improve the user experience and provide accessibility options for users. By using the styled-components library and the localStorage API, we can easily add this functionality to our applications with minimal code.

Here are some tips for troubleshooting and debugging theme issues:

  • Make sure that you have correctly imported the required libraries and dependencies
  • Check for typos and syntax errors in the code
  • Use the browser dev tools to inspect the styles and verify that the correct theme styles are being applied

Here are some additional resources for learning more about implementing themes in React:

I hope this tutorial was helpful and you were able to successfully implement a light and dark theme in your React application. Happy coding!

Snehasish Konger
Snehasish Konger

Snehasish Konger is the founder of Scientyfic World. Besides that, he is doing blogging for the past 3 years and has written 300+ blogs on several platforms. He is also a front-end developer and a sketch artist.

Leave a Reply

Your email address will not be published. Required fields are marked *