Skip to content

handle addEventListener in if condition based on localStorage boolean value

I’m trying to switch the theme based on OS level light/dark mode. Users may change the system settings while using the website. So, I need to update in real-time instead of page refresh. So, I’m using addEventListenerto get system current changes. addEventListener works fine. But, It should work if the System Settings option is set to true.

I have stored System Settings as a boolean option in localStorage. If it is true then the only addEventListener should work. If it is false it should not work. But, my problem is addEventListener work in both cases. I mean it works if System Settings is neither true nor false. How do I handle addEventListener should work based on localStorage value (if System Settings sets true)?

JsFiddle

JS

function defaultFunction() {
    localStorage.setItem('option', 'default');
  localStorage.setItem('systemOption', false);
}
defaultFunction();

function myFunction() {
  let getOption = localStorage.getItem('option');
  let themeDiv = document.getElementById('theme');
  
  if(localStorage.getItem('systemOption') == 'true') {
    let osTheme = window.matchMedia('(prefers-color-scheme: dark)');
    osTheme.addEventListener('change', event => {
      if(event.matches) {
        themeDiv.classList.add("dark");
        themeDiv.classList.remove("default");
      } else {
        themeDiv.classList.add("default");
        themeDiv.classList.remove("dark");
      }
    })
  } else {
    if(getOption == 'dark') {
      themeDiv.classList.add("dark");
      themeDiv.classList.remove("default");
    } else if(getOption == 'default') {
      themeDiv.classList.add("default");
      themeDiv.classList.remove("dark");
    }
  }
}
myFunction();

function setDark() {
    localStorage.setItem('option', 'dark');
  myFunction();
}

function setLight() {
    localStorage.setItem('option', 'default');
  myFunction();
}

function checkBox() {
    let cBox = document.getElementById('system');
  let sun = document.getElementById('sun');
  let moon = document.getElementById('moon');
  
  if(cBox.checked) {
    localStorage.setItem('systemOption', true);
    sun.classList.add('addOpacity');
    moon.classList.add('addOpacity');
  } else {
    localStorage.setItem('systemOption', false);
    sun.classList.remove('addOpacity');
    moon.classList.remove('addOpacity');
  }
  myFunction();
}

Answer

I think the problem is you are adding an event listener but you never removed it thus it’s always listening for that event.

Try adding/removing event listener conditionally like below

function changeListener(event) {
  if(event.matches) {
    themeDiv.classList.add("dark");
    themeDiv.classList.remove("default");
  } else {
    themeDiv.classList.add("default");
    themeDiv.classList.remove("dark");
  }
}


let osTheme = window.matchMedia('(prefers-color-scheme: dark)');
if(localStorage.getItem('systemOption') === 'true') {
    osTheme.addEventListener('change', changeListener);
} else {
    osTheme.removeEventListener('change', changeListener);
}

OR

Listen for event always and apply theme conditionally by checking localStorage

const osTheme = window.matchMedia('(prefers-color-scheme: dark)');
osTheme.addEventListener('change', event => {
    if(localStorage.getItem('systemOption') === 'true') {
        if(event.matches) {
            themeDiv.classList.add("dark");
            themeDiv.classList.remove("default");
        } else {
            themeDiv.classList.add("default");
            themeDiv.classList.remove("dark");
        }
    }
});