ReactJs Guide

Toggle Theme in ReactJs

A comprehensive guide to toggle between dark theme and light theme in ReactJs.

Nimish Jain
5 min readOct 18, 2021

Developers use several methods to toggle between dark mode and light mode. However, most of them make use of excess lines of code or have unnecessary complications. Having struggled with the same issue in my initial projects, I decided to write this article.

GitHub Repository

This feature makes use of

  • localStorage to save the theme for future reference,
  • useContext to make the theme variables and functions easily available throughout the project,
  • useState for theme state management,
  • useEffect to update localStorage whenever the theme is changed, and
  • CSS variables (also known as custom properties or cascading variables) to store the CSS properties for both themes.

Repository Structure

root
├── public
│ ├── favicon.ico
│ ├── index.html
└── manifest.json

├── src
│ ├── assets
└── asset files

├── Components
├── Header
├── Header.js
└── header.css

└── Landing
├── Landing.js
└── landing.css

├── App.css
├── App.js
├── index.js
└── Theme.js

├── .gitignore
├── README.MD
├── package-lock.json
└── package.json
(end)

Step 1: Theme.js

This function is used to control the theme using various React Hooks and Local Storage.

  • The object ThemeContext is created using createContext(), a React Hook which enables us to define the context Object which stores some data and will make it available throughout the project without passing the data as props.
  • ThemeContext is then used to create ThemeContext.Provider which provides value to the children elements. The object that is needed to be provided is added to the value attribute.
  • The variable theme is created using useState(), a React Hook that allows us to have state variables in functional components. Pass the initial state to this function and it returns a variable with the current state value and another function to update this value.
  • The function getTheme() is used to get the value for the key theme from the localStorage. If the key is not present then it sets its value to “dark-theme”, and also returns the same.
  • The function toggleTheme() is used to toggle the state variable theme from “dark-theme” to “light-theme”, and vice-versa.

Step 2: index.js

ThemeProvider wraps around <App /> in /src/index.js so that the value inside ThemeContext is universally available to all the components inside App.

Step 3: App.js

We can access the context data from ThemeContext using const { theme } = useContext(ThemeContext). The value of theme is either “dark-theme” or “light-theme” and is added to className of the outermost div. This will make more sense in Step 4.

Step 4: App.css

All the CSS variables are stored in App.css. You are free to use any other CSS file name, but make sure it is imported in App.js to make it accessible throughout the project. It has the following features:

  • The :root element contains all the CSS Variables for both dark-theme and light-theme. For the sake of this project, primary and secondary text and background colors are taken.
  • There are two class elements called “light-theme” and “dark-theme” which consists of the variables that will be used in the project. Suppose, the value of the state variable theme is “light-theme”, then the className of <App> will consist of “light-theme” and the variables contained in .light-theme will be applied to the entire project.
  • Note that the CSS variable names used in “light-theme” and “dark-theme” are the same. The variables used for this project are --text-primary , --text-secondary , --bg-primary , --bg-secondary and --bg-navbar.
  • You are free to use any variable names of your choice. Refer to this article if you want to learn more about CSS variables.

Step 5: Toggle button

For the sake of this project, I have set up the toggle button in the Header component. Here we simply access the context data from ThemeContext using const { theme, toggleTheme} = useContext(ThemeContext).

The theme changes when thetoggleTheme() function as in Line 13 is triggered.

Ps: This project does not use any fancy toggle switches for switching between themes. You can check out this article by David Herbert to create some awesome Animated Toggle Switches.

Live Preview

CodeSandbox by Nimish Jain

CodeSandbox Link: https://codesandbox.io/s/theme-toggle-h54n8
GitHub Repo Link: https://github.com/nimishjn/nimishjn

How to change an image based on the theme?

This can be achieved by two methods depending on your image file type:

SVG Files:

  • The color of the SVG image can be changed by changing the fill attribute inside its code. For example, the fill attribute of the path element inside LOGO.svg is set to var(--text-primary).
<path d="M17.3681 56.3279…" fill="var(--text-primary)" />
  • However, for this to work the SVG file has to be imported as a ReactComponent and embedded as an independent element as given below:
import { ReactComponent as CompanyLogo } from "LOGO.svg";<CompanyLogo />

Any file extension:

  • This is achieved by importing two images (one for dark theme and one for light theme). An example for the same is given below:
import LogoLightTheme from "logoLight.png";
import LogoDarkTheme from "logoDark.png";
  • The src attribute of img tag is toggled based on the value of theme variable as given below:
<img src={theme === "light-theme" ? LogoLightTheme : LogoDarkTheme} alt="Company Logo" />

Conclusion

This method can also be used for switching between various themes in a website, and not just light theme and dark theme. It can also be implemented for changing the themes (or properties) of a particular component of the website (like a code editor, cards, badge, etc). More variables can be added to ThemeContext to make them available throughout the project.

References

--

--

Nimish Jain
Nimish Jain

Written by Nimish Jain

Full-Stack Developer | Data Analytics Researcher

Responses (1)