Subscribe on changes!

old value and new value equal for deep watching injected value

avatar
Oct 26th 2021

Version

3.2.20

Reproduction link

codesandbox.io

Steps to reproduce

I provide a data (keyed by todoLength) wrapped by computed in App.vue. I inject the todoLength in the child component HelloWorld.vue, and I want to observe the todoLength change in the child component, so I deep watch the todoLength key. Then I change the todoLength in the App.vue, the expression in the template is render correctly. But the watch callback is not called correctly, I expect the old.value is not equal to new.value, but the reality is reverse.

What is expected?

The watch callback is correctly called, ie, the new.value is not equal to old.value.

What is actually happening?

Watch callback is not correctly called, the new.value is equal to old.value. If I want it to work correctly, I should wrap the injected value by the computed api, and watch the according computed key.

avatar
Oct 26th 2021

this is expected. the old array is the same as the new array - you mutated the same array, you did not create a new array. So the old and new value are the same (array).

avatar
Oct 26th 2021

posva I've reopened as I misinterpreted the issue, it's about todo's length, not the array itself. i wanna take a second look and close it if it's still not a bug.

avatar
Oct 26th 2021

Ok, Identified the issue. Injected ref can't be properly observed in Options API's watch: feature

  • with deep: true it it treated as a deeply watched object, ending up as the same ref for new and old value.
  • without deep: true, watch won't fire as the instance property doesn't change - it's still the same ref.

However: The solution will be provided in the next minor and can be opted into with app.config.unwrapInjectedRef = true - as is explained in the console warnings.

So as the next minor will fix this issue with default options that you can already opt-into now, I'll close this.