[Vuejs]-Vue – Remove listener when value in vuex store changes

0πŸ‘

I suspect the problem is not the watcher, but it’s difficult to tell with the code shown in question. Assuming the active watcher is the problem…

The $watch() call returns a function that removes the watcher, so you could use it in your callback when currentAutomaticValue is falsy:

export default {
  created() { πŸ‘‡
    const unwatch = this.$store.watch(
      (state) => {
        return state.settings.colorSettings.automatic;
      },
      (currentAutomaticValue) => {
         if (currentAutomaticValue) {
           //...

         } else {
           // no longer need to watch
           unwatch() πŸ‘ˆ
         }
      },
      { immediate: true }
    )
  }
}

This has a caveat in that if you need to re-enable the watcher, you’ll have to create a new one, so I recommend moving this watcher setup from created() into a method that could be called when needed.

0πŸ‘

So removing the EventListener apparently works after all. I tried to do this before but didn’t get it to work then.

Code needs optimization (suggestions are very welcome!), code looks very messy. But this is a start.

What i did:

  • Made a seperate function setTheme() for the listener so that i’m able to remove it

  • Had to put window.matchMedia("(prefers-color-scheme: dark)") in a constant, this was also needed to be able to remove it

  • Remove the listener when the watcher sees that currentAutomaticValue is false

     methods: {
      setTheme(e) {
        const darkMode = e.matches ? true : false;
        document
          .getElementsByTagName("html")[0]
          .setAttribute(
            "theme",
            darkMode ? "theme-dark" : "theme-default"
          );
      }
    },
    created() {
      const media = window.matchMedia("(prefers-color-scheme: dark)");
    
      this.$store.watch(
        (state) => {
          return state.settings.colorSettings.automatic;
        },
        (currentAutomaticValue) => {
          if (currentAutomaticValue) {
            if (
              window.matchMedia &&
              window.matchMedia("(prefers-color-scheme: dark)").matches
            ) {
              document
                .getElementsByTagName("html")[0]
                .setAttribute("theme", "theme-dark");
            } else {
              document
                .getElementsByTagName("html")[0]
                .setAttribute("theme", "theme-default");
            }
            media.addEventListener("change", this.setTheme);
          } else {
            media.removeEventListener("change", this.setTheme);
            if (this.colorSettings.darkMode) {
              document
                .getElementsByTagName("html")[0]
                .setAttribute("theme", "theme-dark");
            } else {
              document
                .getElementsByTagName("html")[0]
                .setAttribute("theme", "theme-default");
            }
          }
        },
        { immediate: true }
      );
    }
    

Leave a comment