skip to Main Content

How can I prevent the watch function from being triggered for a key other than the one selected in the data array?


import { useSessionStorage } from "@vueuse/core";

const defaultState = {
  data: [
    { key: 1, name: "A" },
    { key: 2, name: "D" },
    { key: 3, name: "C" },
  ]
}

const state = useSessionStorage("settings", defaultState, {
  mergeDefaults: true,
});

const key0Name = toRef(
  () => state.value.data[0].name
);
watch(key0Name, (newOpts) => {
  console.log("key0Name", newOpts);
});

state.value.data[0].name = "Z" // Triggers watch function.
state.value.data[1].name = "Z" // Also triggers watch function.

2

Answers


  1. Chosen as BEST ANSWER

    It looks like I have to use toRefs on the array of objects.

    const data = toRefs(state.value.data);
    
    watch(data[0], ...)
    

    And if I want to watch the name:

    const name0 = toRef(data.name)
    
    watch(name0, ...)
    

  2. It doesn’t when I try it out. Only changes to the value at index 0 trigger the watcher:

    const { createApp, ref, toRef, watch } = Vue;
    console.clear()
    
    const state = ref({
      data: [
        { key: 1, name: "A" },
        { key: 2, name: "D" },
        { key: 3, name: "C" },
      ]
    })
    const key0Name = toRef(
      () => state.value.data[0].name
    );
    watch(key0Name, (newOpts) => {
      console.log(" --> triggered watcher on index 0", newOpts);
    });
    
    const setName = (ix, val) => {
      console.log(`setting at index ${ix} to ${val}`)
      setTimeout(() => state.value.data[ix].name = val) // use timeout to processed changes seperately
    }
    setName(0, 'X')
    setName(0, 'Y')
    setName(1, 'A')
    setName(1, 'B')
    setName(0, 'Z')
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search