Subscribe on changes!

injected ref value is not reactive when updated inside setup of a child component

avatar
Sep 3rd 2020

Version

3.0.0-rc.10

Reproduction link

https://codesandbox.io/s/admiring-snow-4u748?file=/src/Child.vue

Steps to reproduce

Open the reproduction link, in parent component setup we have:

 setup() {
    const msg = ref("initial");
    provide("CONTEXT", { msg });

    return {
      msg
    };
  }

and in a child component setup:

  setup() {
    const ctx = inject("CONTEXT");

    // not working (works when wrapped inside onBeforeMount)
    ctx.msg.value = "updated";
  }

What is expected?

the screen should show: "updated"

What is actually happening?

the screen shows "initial"


It works fine when wrapped inside a lifecycle hook:

onBeforeMount(() => {
    ctx.msg.value = "updated";
})

I'm not sure if it's a bug or intentional behavior, but I find it weird since the parent's setup function is executed before the child's.

avatar
Sep 4th 2020

The usage here is different from the document. 🧐

However, there are times where we need to update the data inside of the component where the data is injected. In this scenario, we recommend providing a method that is responsible for mutating the reactive property.

avatar
Sep 4th 2020

@Picknight providing a method that updates the ref and calling it in the child's setup makes no difference. https://codesandbox.io/s/elated-meadow-6r04w?file=/src/Child.vue

avatar
Sep 4th 2020

The deep reason is ac81dcf. @yyx990803 Maybe we should revert it ?

avatar
Jun 29th 2021

I see this issue is closed but I am not seeing any conclusion on this thread. Am I missing something? I am also looking for solution to my problem.

avatar
Jul 11th 2021

I'm trying to inject a Boolean value into all components (SFC), which provide/inject seems best suited for. I have Vue 3.1.2.

I tried calling:

const injectedRef = ref(getCurrentState())
app.provide('injectedName', injectedRef)

UZu7neyjaw

const injectedComputed = computed(() => injectedRef)
app.provide('injectedName', injectedComputed)

9JUlnMXIWO

const injectedReactive = reactive({ injectedRef })
app.provide('injectedName', injectedReactive)

zWJglrBvjm

As you can see, only the last method worked, but that defeats the purpose of injecting a single true/false variable that can be used directly in components.

This was previously done with:

const reactiveProxy = Vue.observable({ state: getCurrentState() })

Vue.use({
  install (vueInstance) {
    Object.defineProperty(vueInstance.prototype, '$injectedName', {
      get: () => reactiveProxy.state
    })
  }
})