user12763413
user12763413

Reputation: 1349

Mounted in child component executes before parent component created issue

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

Answers (3)

tony19
tony19

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

Pwntastic
Pwntastic

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

Arc
Arc

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

Related Questions