Manually created EffectScopes get deactivated in dev environments when setting a ref used in a component template.
milo-brandt-1 opened this issue · comments
Version
2.7.14
Reproduction link
Steps to reproduce
Inside of a callback passed to effectScope.run and while in development mode (i.e. NODE_ENV !== 'production'), modify a value that is used in a component's template. After doing this, the effectScope will no longer be active (e.g. getCurrentScope() will return undefined, despite being within the effectScope.run callback).
What is expected?
Within the callback passed to effectScope.run, getCurrentScope should always return effectScope.
What is actually happening?
Within the callback passed to effectScope.run, getCurrentScope only returns effectScope until a ref used in a component is modified. The error only occurs in dev environments.
Ran into this while debugging some code that manages various composables with lifetimes not strictly tied to any particular component of the page, but where the data from these composables is used in rendering. I noticed warnings from onScopeDispose in development environments and also differing behavior of getCurrentScope() in dev vs. production builds.
I'm pretty sure the code at fault is here: https://github.com/vuejs/vue/blob/main/src/core/instance/lifecycle.ts#L393
In development environments, this function gets called when rendering is triggered (to support the onRenderTrigger lifecycle hook). It changes some global state around the active scope/component and fails to restore it if invoked from within a manual effect scope. the fuction stores the currently active component (which will be undefined within a manual effect scope), then activates the component for which the hook was triggered, then re-activates the previous component. Within a manual effect scope, this has the effect of setting the activeEffectScope global variable to undefined, despite being within a scope.