2
\$\begingroup\$

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:

  1. Needs to check the users' system preference for light/dark

  2. Needs to persistently keep users light/dark preference throughout the site

  3. 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;
```
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Apr 14, 2020 at 15:27
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

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;
answered Apr 15, 2020 at 7:11
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.