ReactJs Guide
Toggle Theme in ReactJs
A comprehensive guide to toggle between dark theme and light theme in ReactJs.
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 updatelocalStorage
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 usingcreateContext()
, 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 createThemeContext.Provider
which provides value to the children elements. The object that is needed to be provided is added to thevalue
attribute.- The variable
theme
is created usinguseState()
, 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 keytheme
from thelocalStorage
. 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 variabletheme
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 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 thepath
element inside LOGO.svg is set tovar(--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 ofimg
tag is toggled based on the value oftheme
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.