-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
$watch can register it's effects on the wrong instance #2381
Comments
watch effects created with so my first suspicion was that the effects simply were already cleanup up when your code is called by that's not the case, so something we should probably take a look at. |
I tried boiling it down but couldn't: https://jsfiddle.net/posva/gtmksj37/ Please open a new issue if you manage to provide a boiled down reproduction |
Are you serious? |
Not sure If you misunderstood my intentions.
https://jsfiddle.net/85geva61/ We can't debug your whole project with our ressources. If you want to make it easier for us to identify a potential issue, try stripping your code down until no other effects are in play to the best of your abilities. |
While I don't have a miniscule repro yet, I did figure out what the bug is. Please add the following assertion to vue.js and then try out some non-trivial apps that use $watch, in particular call --- ./node_modules/.vite_opt_cache/vue.orig
+++ ./node_modules/.vite_opt_cache/vue.js
@@ -3172,6 +3172,7 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM
onTrigger,
scheduler
});
+ console.assert (instance == currentInstance);
recordInstanceBoundEffect(runner);
// initial run
if (cb) { Here's why things break, The fix is obviously to change the call to Now, speculating, the current code tends to add runners to the wrong (current) instance whenever doWatch is called with an explicit instance that is not currentInstance. That behaviour can generally be expected to cause spurious rendering updates (a runner still active on the wrong instance after it should have been stopped), and cause missing updates other times (the runner was stopped too early during unmount of the wrong instance it was attached to). Unfortunately I cannot reopen this issue, so please do that for me. |
I'll reopen this so we can re-evaluate, thanks so far. |
Managed to reproduce it: https://jsfiddle.net/Linusborg/4w8gjvph/6/ Still looking into the specifics of what happens and wether tim-janik's proposed fix is the right one, but as he explained, it's related to a mismatch of As Even more limiting - the issue only happens as long as the child itself doesn't have any So one way to fix the error being thrown is by checking for the existance of effects here: like so: instance.effects && remove(instance.effects!, runner) Another way would be to initialize Both of these fixes would presuppose that the behaviour of So then we have to fix maybe something like export function recordInstanceBoundEffect(effect: ReactiveEffect, instance?: ComponentInternalInstance) {
if (!instance && currentInstance) {
instance = currentInstance
}
if (instance) {
;(instance.effects || (instance.effects = [])).push(effect)
}
} |
it should always add its effects to its own instance close: #2381
Version
3.0.0
Steps to reproduce
I'm in the process of porting a smallish front-end (10klocs) from Vue2 to Vue-3.0.0.
I have one mixin that installs a watch and uninstalls it like this (abbreviated):
Calling unwatch1 always triggers the following:
It looks like Vue's unwatch callback as returned from $watch() cannot remove itself from
instance.effects
, since vue.js reads:Since I'm in the middle of a transition, it's impossible for me to deduce a minimal test case.
I hope the trace is useful regardless.
The full (unported) Vue2 based code can be found here, still using beforeDestroy instead of beforeUnmount:
https://github.com/tim-janik/beast/blob/7e743157617f74f842aabbe6efbff2184b0b1109/ebeast/util.js#L696
What is expected?
unwatch() as returned from $watch() can be called without exception.
What is actually happening?
An exception is thrown.
The text was updated successfully, but these errors were encountered: