Subscribe on changes!

No forceUpdate() in Vue 3 with compositionAPI

avatar
Apr 8th 2021

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()

avatar
Apr 8th 2021

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'
avatar
Apr 8th 2021

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?

avatar
Apr 8th 2021

Oh...sorry.... yes, that should be instance

avatar
Apr 8th 2021

Oh...sorry.... yes, that should be instance

by the way, I don't find a function named queueJob, is it the same with nextTick?

avatar
Apr 8th 2021

Should be queuePostFlushCb:

import { queuePostFlushCb } from 'vue'

I don’t recommend this, but it seems to be the only workaround at the moment

avatar
Apr 8th 2021

@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.

avatar
Apr 8th 2021

The queueJob will put the update task in the async queue, and can de-duplicate the update task

avatar
Apr 8th 2021

Thanks @HcySunYang

avatar
Apr 8th 2021

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?

avatar
Apr 8th 2021

$forceUpdate() is still there:

  
  setup() {
      const instance = Vue.getCurrentInstance()
    
    console.log(instance.proxy.$forceUpdate)
  }
avatar
Apr 8th 2021

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.

avatar
Apr 8th 2021

Yeah, I agree with @LinusBorg

avatar
Apr 8th 2021

@LinusBorg Yes, I was stuck until I find this internal instance approach. Wish $forceUpdate can be exposed to developers.

avatar
Apr 8th 2021

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

avatar
Apr 9th 2021
export function useForceUpdate() {
  const instance = getCurrentInstance()
  return () => instance.proxy.$forceUpdate()
}

@posva , Looks great 👍

avatar
Apr 9th 2021

we could alternatively add it to context?

avatar
Apr 9th 2021

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

avatar
Apr 10th 2021

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.

avatar
Apr 10th 2021

@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.)

avatar
Jun 13th 2022

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

avatar
Jun 13th 2022
avatar
Jun 13th 2022

@whylost wrap your state class instance in a shallowRef: https://vuejs.org/guide/extras/reactivity-in-depth.html#integration-with-external-state-systems

thanks

avatar
Jan 21st 2024

@yyx990803 Then you could argue that exposing it for the Options API could be declared deprecated. If there's a reason to continue keeping it around for the Options API, then that same reason should be just as valid for Composition API.