javascriptvue.jsvuejs2inject

Vue Js 2 provide cannot be updated in Parent


I'm trying to use the provide functions in Vue.js 2.7 and i want to update one of the props through an async function but it doesn't update the injection in the children

Parent.vue

<template>
    <Child />
</template>

<script>
export default {
    provide(){
        return {
            typesTabs: null,
            instanceTypeToAdd: null,
            buttonInstanceTypeToAdd: null,
            updateProvidedPropValue: this.updateProvidedPropValue
        }
    },
    mounted(){
       this.fetchInstances()
    },
    methods: {
        updateProvidedPropValue(propName, value) {
            this[propName] = value
        },
        async fetchInstances() {
            axios.get().then(() => {
                this.typesTabs =
                    JSON.parse(JSON.stringify(res.data.expense_income_type_consts))
            })
        }
    }
}
</script>

Child.vue

<template> 
    <div 
        v-for="tab in typesTabs" 
        @click="updateProvidedPropValue('instanceTypeToAdd', tab)"
    > 
        {{ tab.name }} 
    </div>
</template>

<script>
    export default {
        inject: ['typesTabs', 'instanceTypeToAdd', 'updateProvidedPropValue']
    }
</script>

while the updateProvidedPropValue works properly IF i give the typesTabs object hard coded, when it's loading asynchronously the typesTabs doesn't contain anything so i can't change the instanceTypeToAdd.

I tried to console.log(this.typesTabs) in Parent.vue right after the axios request and it's filling the prop (typesTabs) propperly, but does not update to show content in children.


Solution

  • From the documentation.

    Note: the provide and inject bindings are NOT reactive. This is intentional. However, if you pass down an observed object, properties on that object do remain reactive.

    You can use a data and computed property together as a work-around

    import { computed } from 'vue';
    
    ...
    
    provide() {
      return {
        typesTabs: computed(() => this.tabs),
        instanceTypeToAdd: null,
        buttonInstanceTypeToAdd: null,
        updateProvidedPropValue: this.updateProvidedPropValue
      };
    },
    data() {
      return {
        tabs: []
      };
    },
    
    axios.get().then(() => {
      this.tabs =
        JSON.parse(JSON.stringify(res.data.expense_income_type_consts))
    })