jjoan
jjoan

Reputation: 393

Vue: Waiting for props before mounted is run

I have component, ShopCart.vue (code below), that is receiving props from the parent. One of those props is cartItems. I am running a function on the cartItems in mounted() but to make sure the props were ready, I put them in Vue.nextTick, which I saw as a solution here on StackOverflow. That seemed to resolve the issue but I noticed it wasn't reliable and there were instances where the cartItems would be empty when the function was ready. To test this, I put them in a setTimeout for 3 seconds and then the cartItems had 20 passed items, so I know it's working..it's just running too quickly. How can I resolve this to ensure the props are ready in this component?

Part of the ShopCart.vue

export default {

data() {
    return {
        dataLoaded: false,
        modalType: null,
        orderNotes: null, 
        test: null,
        expireTimes: {

        }
    }
},
props: {
        cartItems:  {type: Array},
        cart:       {type: Object},
        customer:   {type: Object}
    },
mounted() {
    let vm = this;      

    Vue.nextTick(() => {
        vm.cartItems.forEach((item, index) => {
            Vue.set(vm.expireTimes, item.item_id, "")
            this.checkItemExpiry(item.expire_at, item.item_id)

        });
    });

}

Upvotes: 5

Views: 7607

Answers (4)

coenni
coenni

Reputation: 422

this._props.cartItems can be reached inside mounted() in vue2

Upvotes: 0

Francisco Hanna
Francisco Hanna

Reputation: 1137

You could try using Vue's watch property over the cartItems prop so when it changes you can then process it, like so:

watch: {
    cartItems(newVal) {
        newVal.forEach((item, index) => {
            Vue.set(vm.expireTimes, item.item_id, "")
            this.checkItemExpiry(item.expire_at, item.item_id)
        });
    }
}

Make sure to pass an empty array if the cartItems is not ready in the parent component, or validate with something like if(newVal){ ... } before the forEach iteration.

Upvotes: 5

Radu Diță
Radu Diță

Reputation: 14211

Vue.nextTick is usually used when updating a reactive component and you want to use the DOM with the updated value. Vue.nextTick is not intended for async operations, as the time for the async operation is not known in advanced.

Your best bet is to use a v-if when disaplaying the content. This will also allow you to use v-else and maybe show a preloader.

Upvotes: 0

Efrat Levitan
Efrat Levitan

Reputation: 5632

@Francisco Hanna's answer will work for you, but you can avoid a watcher (which is consuming resources) if you simply use v-if to render the shopCart component only after any cartItems exist:

in the parent component:

<shop-cart :cartItems="cartItems" v-if="cartItems.length"></shop-cart>

Upvotes: 13

Related Questions