简体   繁体   中英

Vue watcher data not updating correctly

I have a watcher on a value of an object, I do an api call to get some data if the value is true, but it seems like the data in my local state is updating a tick too late.

If the condition is true nothing is set and I switch it back to false then the data is being set.

This is my code:

props: {
  simulation: {type: Simulation, default: () => new Simulation()}
}
data() {
  return {
    loadedStores: []
  }
},
watch: {
  'simulation.fetch': function () {
      if (this.simulation.fetch) {
        axios.get(`some-url`)
          .then((response) => {
            this.loadedStores = response.data.data;
          })
      }
  }
}

simulation.fetch updates to true or false through a select option in my interface.

I am not sure what I am doing wrong here. I've tried wrapping it with this.$nextTick(() => {}) but that doesn't weem to be doing anything

You can use deep watcher for this so that the callback will be called whenever any of the watched object properties change regardless of their nested depth:

watch: {
  simulation: {
    handler: function() {
      console.log(this.simulation.fetch)
      if (this.simulation.fetch) {
        // axios call here
      }
    },
    deep: true
  }
}

Your watch code would have worked fine, if fetch was defined in the data option and if simulation was not a prop actually like:

data() {
  return {
    loadedStores: [],
    simulation: {
      fetch: false 
    }
  }
},

This change detection caveat is explained in details here

I tried to reproduce your problem and the only issue I see is when Simulation.fetch starts with true . watcher doesn't get called and for that you might use mounted() hook

 class Simulation { constructor() { this.fetch = true; this.timeout = 1000; this.handle = null; const loop = () => { this.fetch =.this;fetch. this,handle = setTimeout(loop. this;timeout). } this,handle = setTimeout(loop. this;timeout). } } Vue,component("test": { template: `<div><div,key="item" v-for="item in loadedStores">{{item}}</div></div>`: props: { simulation: { type, Simulation: default, () => new Simulation() } }: data() { return { loadedStores, [] } }: watch. { 'simulation:fetch'. function () { this;tryGetData(), } }: methods. { tryGetData() { if (this.simulation.fetch) { this.loadedStores = [...Array(Math.floor(Math.random() * 10)),keys()] } } }. mounted() { this;tryGetData(): } }) new Vue({ el: '#app' })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <test></test> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM