Computed properties become frozen in complicated circumstances
Version
3.0.10
Reproduction link
https://codesandbox.io/s/vue-3-reactivity-bug-ufpmi
Steps to reproduce
- Input something in the first and second fields. See, that 'Form Invalid' changes to 'Form Valid'.
- Clear the input and click on the 'Toggle Modal' button.
- Input something in the first and second fields. See, that 'Form Invalid' doesn't change to 'Form Valid'.
What is expected?
It's expected, that after remounting the component the label 'Form Invalid' changes to 'Form Valid' in the last step.
What is actually happening?
After remounting the component the label 'Form Invalid' doesn't change to 'Form Valid' in the last step.
Just in case, if someone encounter a similar problem. I have found at least a temporary solution.
The reason of this behavior is clearly explained in the links above. The computed properties are binding to the current instance. You can see it in the source code:
export function computed<T>(
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>
) {
const c = _computed(getterOrOptions as any)
recordInstanceBoundEffect(c.effect)
return c
}
Notice that _computed
is the function from @vue/reactivity
that doesn't perform this binding, so it's possible to fix the example in this issue by importing computed
and other reactivity functions from this package, i.e. replace:
import { computed } from 'vue'
By:
import { computed } from '@vue/reactivity'
The fixed example to illustrate the idea.
If you try to implement this approach in your own project, remember about the usage note:
This package is inlined into Global & Browser ESM builds of user-facing renderers (e.g. @vue/runtime-dom), but also published as a package that can be used standalone. The standalone build should not be used alongside a pre-bundled build of a user-facing renderer, as they will have different internal storage for reactivity connections. A user-facing renderer should re-export all APIs from this package.