I have a dark theme toggle switch for my React component that works well, but I know the code could use some work. First I am checking to see what the users' preferences are for light/dark. Then I am setting in local storage what the user has chosen as a preference and then also checking for that value. I'm still learning and would like some feedback.
My requirements:
Needs to check the users' system preference for light/dark
Needs to persistently keep users light/dark preference throughout the site
Add class dark to the body tag in order to active all the CSS changes
import React, { Component } from "react";
class LightDarkToggle extends React.Component {
componentDidMount() {
let bodyClassList = document.body.classList;
let themeSwitch = document.getElementById('switch-style');
//Here we are checking the USERS' device settings for dark theme
if(window.matchMedia('(prefers-color-scheme: dark)').matches) {
bodyClassList.add('dark');
themeSwitch.checked = true;
}
else if(window.matchMedia('(prefers-color-scheme: light)').matches) {
bodyClassList.remove('dark');
themeSwitch.checked = false;
}
//Persisting USERS' theme preference by checking the local storage we set
if(window.localStorage.getItem('theme') === 'dark') {
bodyClassList.add('dark');
themeSwitch.checked = true;
}
else if(window.localStorage.getItem('theme') === 'light') {
bodyClassList.remove('dark');
themeSwitch.checked = false;
}
}
handleClick() {
document.body.classList.toggle('dark');
if(document.getElementById('switch-style').checked === true){
window.localStorage.setItem('theme', 'dark');
}
else if (document.getElementById('switch-style').checked === false){
window.localStorage.setItem('theme', 'light');
}
}
render() {
return (
<div className="toggle-mode">
<div className="icon">
<i className="fa fa-sun-o" aria-hidden="true"></i>
</div>
<div className="toggle-switch">
<label className="switch">
<input type="checkbox" id="switch-style" onClick={this.handleClick} />
<div className="slider round" id="lightDarkToggle"></div>
</label>
</div>
<div className="icon">
<i className="fa fa-moon-o" aria-hidden="true"></i>
</div>
</div>
);
}
}
export default LightDarkToggle;
```
1 Answer 1
Here are some suggestions:
handleClick
method
Intead of calling document.getElementById
and checking for .checked
twice, you can store it's value into a constant like this:
const isDarkMode = document.getElementById("switch-style").checked;
then just do window.localStorage.setItem("theme", isDarkMode ? "dark" : "light");
After these changes, the method will look like this:
handleClick() {
document.body.classList.toggle("dark");
const isDarkMode = document.getElementById("switch-style").checked;
window.localStorage.setItem("theme", isDarkMode ? "dark" : "light");
}
componentDidMount
method
This code can be simplified
if (window.localStorage.getItem("theme") === "dark") {
bodyClassList.add("dark");
themeSwitch.checked = true;
} else if (window.localStorage.getItem("theme") === "light") {
bodyClassList.remove("dark");
themeSwitch.checked = false;
}
You could make use of toggle
method's second parameter, which is a boolean value that forces the class to be added or removed, regardless of whether or not it already existed.
So that code could be changed to
const mustUseDarkMode = window.localStorage.getItem("theme") === "dark";
bodyClassList.toggle("dark", mustUseDarkMode);
themeSwitch.checked = mustUseDarkMode;