Set checkbox checked or nonChecked if darkmode is activated | REACT

698 Views Asked by At

Im new in react, i try the reference mode or state mode, but the page render a lot of times, or when i click in my checkbox, dont change the checked option. Im using tailwind darkmode

when i load the page, there are a conditional that check if darkmode is activated or not, so if loadind the page darkmode is enabled, the checkbox must be true and if not must be false, simply

import React, {useEffect, useState} from "react";

function Header() {
    const [darkMode, setDarkMode] = useState(false);
    useEffect(() =>{
        if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
            document.documentElement.classList.add('dark')
            localStorage.theme = 'dark'
            setDarkMode(!darkMode)
          } else {
            document.documentElement.classList.remove('dark')
            localStorage.theme = 'light';
            console.log('modo luz activado')
          }
    },[])
    

  const changeTheme = () => {
    
    if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
      document.documentElement.classList.remove("dark");
      localStorage.theme = "light";
    } else {
      document.documentElement.classList.add("dark");
      localStorage.theme = "dark";
    }
  };
  
  return (
    <header>
      <nav>
        <input checked={darkMode} type="checkbox" onChange={changeTheme} />
      </nav>
    </header>
  );
}

export default Header;
2

There are 2 best solutions below

2
Shreyansh Gupta On BEST ANSWER

You should have your change theme function like this:

const changeTheme = () => {
    localStorage.theme = darkMode ? 'light' : 'dark'
    setDarkMode(!darkMode)
    if (darkMode) {
        document.documentElement.classList.remove("dark");
    } else {
        document.documentElement.classList.add("dark");
    }
};
1
Rubek Joshi On

You would normally use a React.useContext() for changing themes but since you are new here's how I would recommend you to approach this challenge:

import React, {useEffect, useState} from "react";

function Header() {
    const [darkMode, setDarkMode] = useState( // initialize your state here directly
      localStorage.theme === 'dark' ||
      (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
    );
    
    useEffect(() => { // move your logic part here
      if (!darkMode) {
        document.documentElement.classList.add('dark')
        localStorage.theme = 'dark'
      } else {
        document.documentElement.classList.remove('dark')
        localStorage.theme = 'light';
      }
    }, [darkMode])
    

  const changeTheme = () => {
    setDarkMode(!darkMode) // now just worry about changing your state
  };
  
  return (
    <header>
      <nav>
        <input checked={darkMode} type="checkbox" onChange={changeTheme} />
      </nav>
    </header>
  );
}

export default Header;

The benefit of doing it this way is that you are handling your theme logic reactively. You are watching for change in your state and implementing your logic instead of implementing your logic each time and changing your state each time as well.