1

I need help. I'm kind of an amateur in Vue3, and can´t understand why this happens:

If I set this in the parent component:

props: [ 'code' ],    
data() {
    return {
        asset: {
            id: '',
            brand: '',
            group: {
                name: '',
                area: ''
            }
        }
    }
},
created() {
    axios.get('/api/myUrl/' + this.code, {})
        .then(response => {
            if (response.status === 200) {
                this.asset = response.data;
            }
        })
        .catch(error => {
                console.log(error);
        })
}

then, in my component <asset-insurance :asset_id="asset.id"></asset-insurance>, asset_id prop is empty.

But, if I set:

props: [ 'code' ],
data() {
    return {
        asset: []
    }
},
created() {
    axios.get('/api/myUrl/' + this.code, {})
        .then(response => {
            if (response.status === 200) {
                this.asset = response.data;
            }
        })
        .catch(error => {
            console.log(error);
        })
}

then, the asset_id prop gets the correct asset.id value inside <asset-insurance> component, but I get a few warnings and an error in the main component about asset property group.name not being set (but it renders correctly in template).

Probably I'm doing something terribly wrong, but I can't find where is the problem. Any help?

Edit:

I'm checking the prop in child component AssetInsurance just by console.logging it

<script>
export default {
    name: "AssetInsurance",
    props: [
        'asset_id'
    ],
    created() {
        console.log(this.asset_id)
    }
}
</script>

asset_id is just an integer, and is being assigned correctly in parent's data asset.id, because I'm rendering it in the parent template too.

3
  • The code you posted doesn't explain the problem. It should work if data is what you expect. It's unknown how you deternined that a prop is incorrect. The most simple way would be to just output asset.id value, no child component is needed. Please, provide stackoverflow.com/help/mcve to reproduce it. A working demo on Stackblitz, etc may help to get an answer faster. But it's a mistake to define asset as an array and then assign an object. Commented Dec 11, 2021 at 11:40
  • @EstusFlask, thank you, but I'm sorry to say I don't know how to use Stackblitz. I have edited my question to clarify that asset.id is being assigned correctly in the api call, and that a direct console.log in the child component shows that prop is not being passed when I define asset with properties, but it's passed right when declaring asset as an array. :( Commented Dec 11, 2021 at 11:55
  • I posted the explanation. You won't get prop value in created hook because it doesn't exist. I guess you just broke the component when using asset array (this was the reason for errors), so child component was re-mounted the second time when asset.id has been available, while it shouldn't under normal circumstances. Also be aware of this when loggin objects (not the case here) stackoverflow.com/questions/23392111/console-log-async-or-sync Commented Dec 11, 2021 at 12:28

2 Answers 2

1

It's incorrect to define asset as an array and reassign it with plain object. This may affect reactivity and also prevents nested keys in group from being read.

The problem was misdiagnosed. asset_id value is updated but not at the time when this is expected. Prop value is not available at the time when component instance is created, it's incorrect to check prop value in created, especially because it's set asynchronously.

In order to output up-to-date asset_id value in console, a watcher should be used, this is what they are for. Otherwise asset_id can be used in a template as is.

Sign up to request clarification or add additional context in comments.

3 Comments

Ok, now I understand where is the point of the problem, but sadly I don't know how to fix it. What would be the right way of making the api call right in created or mounted hooks? As you indicated, I have created a watcher in computed '''asset_id_watcher() { return this.asset_id }''', but '''console.log(this.assed_id_watcher)''' doesn't work in created or mounted either.
By "watcher" I mean specifically a watcher, not a computed, vuejs.org/v2/guide/computed.html#Watchers . You physically cannot get a value in created or mounted if it doesn't exist yet. You likely have XY problem. If you need asset_id on component init, you shouldn't render it until data is available. This is commonly solved with v-if
Btw, I didn't even know the watch properties. I have been reading, and now I understand how can I fix this whenever it's not possible to use v-if in the component. :)
0

Ok, I think I found the proper way, at least in my case.

Prop is not available in the component because it is generated after the creation of the component, as @EstusFlask pointed.

The easy fix for this is to mount the component only when prop is available:

<asset-insurance v-if="asset.id" :asset_id="asset.id"></asset-insurance>

This way, components are running without problem, and I can declare objects as I should. :)

Thank you, Estus.

1 Comment

Usually you can just define initial asset: null and do v-if="asset" without reproducing the whole structure for asset object, this depends on how it's used in the rest of the component

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.