question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Interesting bug / quirk computed property not updating correctly, but probably not fixable

See original GitHub issue

Hi consider this snippet:

  ...
  computed: {
    someProp() {
      if(this.nonReactiveProperty) {
        return this.reactiveProperty;
      }
   }
  },
  ...

From the documentation I would assume (please show me if I missed something) that someProp() should get re-evaluated when this.reactiveProperty does change. Works as expected as long as this.nonReactiveProprty is true all time. However, if this.nonReactiveProperty is false the first time someProp() is read, then someProp() will never re-evaluate, even if this.reactiveProperty changes (after this.nonReactiveProperty gets true). The problem is, I guess it is not fixable. Am I assuming correctly, that the dependencies of someProp() get calculated the first time it is executed? So code which does not get executed then, vue is just blind of…? This is quite tricky and probably I’ve run into this quite some times before figuring out. It gets even harder to see when inside lazy conditions. E.g. this works all the time:

someProp() {
   if(this.reactiveProperty && this.nonReactiveProperty) {
     return this.reactiveProperty;
   }
}

while this might not:

someProp() {
   if(this.nonReactiveProperty && this.reactiveProperty) {
     return this.reactiveProperty;
   }
}

So if this is not fixable, and I didn’t miss something, I would suggest to add this to the documentation.

EDIT: here is a codesandbox: https://codesandbox.io/s/priceless-leftpad-kktuq?file=/src/App.vue

best Martin

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:15 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
shentaocommented, Apr 10, 2020

@derMart

EDIT: Nvm, noticed you mentioned that in the last reply. 😅 I think that behaviour could be better described in the API docs.

It’s worth adding that (as far as I remember) the dependencies are collected whenever the computed property executes without using the cache. Any dependencies collected during previous runs will also be removed.

So in case you have several conditionals:

someProp () {
  if (this.reactiveProp === 0) {
    return this.anotherReactiveProp
  } else if (this.yetAnotherReactiveProp === 1) {
    return this.nonReactiveProp
  } else {
    return this.alsoReactiveProp
  }
}

When this.reactiveProp === 0 is true, the only dependencies collected will be: this.reactiveProp and this.anotherReactiveProp. When this.reactiveProp === 0 is false and this.yetAnotherReactiveProp === 1 is true, the collected dependencies list will be: this.reactiveProp and this.yetAnotherReactiveProp. When neither of those two conditions pass (final else returns), the list of dependencies will look like this: this.reactiveProp, this.yetAnotherReactiveProp and this.alsoReactiveProp.

As you can see the list of dependencies is dynamic and collected at runtime as it was already mentioned. Which means if during the last execution of that computed property something wasn’t registered as a dependency, changing it won’t trigger a recalculation. And this is ultimately a good thing if you think about it.

0reactions
derMartcommented, Apr 10, 2020

Here is an example codesandbox which tries to reconstruct dependency detection in more detail: https://codesandbox.io/s/nifty-darkness-fqf6x?file=/src/App.vue See the console output and comments. My conclusion of this is, that dependencies are re-tracked every time a re-evaluation of a computed property is triggered. This also means that reactive properties which once were identified dependencies might be removed from the list after a later evaluation during which they were not accessed.

Another conclusion is the workaround suggested by @jacekkarczmarczyk (with a little loss in execution performance): Just put all the needed reactive dependencies as pure statements at the beginning of the computed property, in case of the example above:

computed: {
  someProp() {
    this.reactiveProperty;
    if(this.nonReactiveProperty) {
      return this.reactiveProperty;
    }
  }
}

This will call their getter and mark them as dependent.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Vue.js computed property not updating - Stack Overflow
js computed property but am running into an issue: The computed method IS being called at the correct times, but the value returned...
Read more >
Bug listing with status RESOLVED with resolution FIXED as at ...
... Bug:393 - "portage handles 'emerge --world update' incorrectly; pkg_* functions do not work properly" status:RESOLVED resolution:FIXED severity:normal ...
Read more >
Mozilla Firefox Bug Fixes
Firefox Bug Fixes ; Handle non-finite values for rect per spec · A missing updates property in an update.rdf should be counted as...
Read more >
Vue Computed Property not updating; Troubleshooting Steps
How to troubleshoot the problems that occurred when the computed property does not work or update what we want is explained in this...
Read more >
What Every Computer Scientist Should Know About Floating ...
Unlike the quadratic formula, this improved form still has a subtraction, but it is a benign cancellation of quantities without rounding error, not...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found