Reputation: 1349
I am working on vue application. The issue I am facing here is that the child component mounted is executed before the parent child created.
I am sending props from parent component to child component and I want to use those props in the child component's mounted but I am not getting those props in mounted as they are executed before created in parent. Please help me fix this issue so that child component sets this.userCopy to this.user which is coming as a prop.
parent componeent
<template>
<div>
<Info :user="user" />
</div>
</template>
<script>
import Info from 'views/info';
export default {
components: {
Info
},
data () {
return {
user: {
first_name: '',
last_name: '',
},
errors:[]
}
}
created() {
this.fetchUsers();
},
methods: {
fetchUsers() {
this.$axios.get('/user.json')
.then(response => {
this.user = response.data;
}).catch(error => {
this.errors = error.response.data.error;
});
},
}
}
</script>
child component
<template>
<div>
{{userCopy}}
</div>
</template>
<script>
export default {
props: ['user'],
data () {
return {
userCopy: {}
}
}
mounted: function() {
var that = this;
this.userCopy = this.user
}
}
</script>
Upvotes: 7
Views: 10350
Reputation: 138626
Since user
is updated asynchronously after the component is already mounted, user
would be the initial value (undefined) in the mounted()
hook.
Option 1: The parent could conditionally render the child component based on user
, so that the component's user
prop would have a value upon mounting:
<Info v-if="user" :user="user">
export default {
data() {
return {
user: null, // updated asynchronously in fetchUsers()
}
}
}
Option 2: The child could use a watcher on user
that updates userCopy
:
export default {
//...
watch: {
user(user) {
this.userCopy = { ...user } // shallow copy
}
}
}
Note the use of the spread operator to shallow copy user
.
Upvotes: 7
Reputation: 481
Something I've done is have a loaded
value in my data. Then on that child component that relies on that data, I'll throw a v-if="loaded"
.
data() {
return {
loaded: false
}
},
async created() {
try {
await this.fetchUsers();
// loaded will be set after the users have been fetched.
this.loaded = true;
}
catch(error) {
console.error('Failed to grab the users', error)
}
}
then in your template just do...
<child-component v-if="loaded" />
Upvotes: 1
Reputation: 1078
Actually, your created
is being invoked before your children component's mounted
. The problem is that the fetchUsers
is asynchronous (a Promise) and needs to be awaited.
async created() {
await this.fetchUsers();
},
Try this code, awaiting the asynchronous operation.
Upvotes: 0