Mounted in child component executes before parent component created issue

Viewed 2764

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>
3 Answers

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.

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.

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" />
Related