No forceUpdate() in Vue 3 with compositionAPI
Version
3.0.11
Reproduction link
https://jsfiddle.net/posva/km2qpwx7/
Steps to reproduce
In Vue2 we can call this.$forceUpdate() to force update a component. Once I switched to Vue 3 Composition API, seems this feature is lost... How can I get it back?
What is expected?
I can call $forceUpdate()
What is actually happening?
I cannot call $forceUpdate()
This is indeed a lack of the Composition API, but you can easily use the existing API to make workarounds:
import { queueJob } from 'vue'
const Comp = {
setup() {
const instance = getCurrentInstance()
const $forceUpdate = () => queueJob(instance.update)
}
}
Maybe we need an implementation of the Composition API version of the corresponding capability, e.g.
import { forceUpdate } from 'vue'
This is indeed a lack of the Composition API, but you can easily use the existing API to make workarounds:
import { queueJob } from 'vue' const Comp = { setup() { const instance = getCurrentInstance() const $forceUpdate = () => queueJob(i.update) } }
Maybe we need an implementation of the Composition API version of the corresponding capability, e.g.
import { forceUpdate } from 'vue'
Thanks @HcySunYang, is i
stand for instance?
Oh...sorry.... yes, that should be
instance
by the way, I don't find a function named queueJob
, is it the same with nextTick
?
Should be queuePostFlushCb
:
import { queuePostFlushCb } from 'vue'
I don’t recommend this, but it seems to be the only workaround at the moment
@HcySunYang May I know what is the difference between queuePostFlushCb
and nextTick
? Also, why should I put the update function inside queuePostFlushCb
? Can I call instance.update()
instead? Thanks in advance.
I found that queueJob
is not exposed for us... and queuePostFlushCb
does not have the ability to de-duplicate the callback. May I know if I can use queueJob
here?
$forceUpdate()
is still there:
setup() {
const instance = Vue.getCurrentInstance()
console.log(instance.proxy.$forceUpdate)
}
FWIW, I think it's still worthwhile to provide a bette way to force an update than to go through the internal component instance.
We do want people to rely on this as little as possible, which is also why we don't document anything about it's APIs - it's considered internal and more of an escape hatch for lib authors.
@LinusBorg Yes, I was stuck until I find this internal instance approach. Wish $forceUpdate
can be exposed to developers.
We do want people to rely on this as little as possible, which is also why we don't document anything about it's APIs - it's considered internal and more of an escape hatch for lib authors.
Yeah, what would we expose though?
export function useForceUpdate() {
const instance = getCurrentInstance()
return () => instance.proxy.$forceUpdate()
}
setup() {
const forceUpdate = useForceUpdate()
function doStuff() {
forceUpdate()
}
}
Since it relies on the current instance, I don't think we can directly expose forceUpdate()
Given the nature of this API, I'm not sure if it should be documented instead
export function useForceUpdate() {
const instance = getCurrentInstance()
return () => instance.proxy.$forceUpdate()
}
@posva , Looks great 👍
I think we should avoid exposing a low level utility like forceUpdate()
in such a visible place like the context. I personally think we should document this rather than add useForceUpdate()
because it shouldn't be used most of the time and people should search for this method and inform themselves of what it is intended for rather than just see the name with autocompletion and try to use it
I've actually never for once needed forceUpdate
when using Vue 3 myself. I would rather know what use case this is absolutely needed for.
@yyx990803 I used to develop geographical map with (ArcGIS JSAPI) and using Vue as my web framework. ArcGIS JSAPI has its own reactive system and seems to be implemented by getter/setter (like Vue2). However, I should avoid Vue3 to make it as reactive
so that I always markRaw
to those instances which belongs to this API. The problem is that Vue reactive system won't know when the instance's property is being mutated. Or I should say I know better than Vue in this case. Therefore, I know when should I call $forceUpdate()
in order to update the template. (If part of the template depends on the instance's property.)
Will there be an API for forceUpdate()?
I imported a class instance
(using getter/setter and Proxy but can't use vue's reactive system to wrap it) in vue3 component and need to trigger update manually
@whylost wrap your state class instance in a shallowRef: https://vuejs.org/guide/extras/reactivity-in-depth.html#integration-with-external-state-systems
@whylost wrap your state class instance in a shallowRef: https://vuejs.org/guide/extras/reactivity-in-depth.html#integration-with-external-state-systems
thanks