Async lifeCycle hooks may cause props to be undefined

Introduction

Have you ever passed down props from parent to a child component in vue only to realize that the prop isn't yet available but showing undefined instead?

Well, one possibility is the presence of async code in lifecycle hooks

Example

// parent.js
<script>
  import Child from './child'
  export default{
    data() {
      return {
        prop: undefined,
      }
    }
    async created() {
      this.prop = await this.$store.dispatch('getProp')
    }
  }
</script>
<template>
  <Child
    :prop=prop
  />
</template>
// child.js
<script>
  export default{
    props: ['prop'],
    created() {
      console.log(this.prop)
    }
  }
</script>
<template>
   ...
</template>

When we pass props from parent components to children, props are available by the time the created hook runs since the parent created hook runs before the child created hook. (The opposite for mounted hook).

However, in cases like the example above console.log(this.prop) will output undefined and that is because the lifecycle hooks themselves are synchronous even if they include async code inside of them.

In the example above, the created hook in the child component will be called immediately after the created hook in the parent component is called. It will not wait for the code inside of it to finish.

In fact, console.log(this.prop) might still result in undefined even if it is called in mounted hook instead. Although, the hooks run in order, the code inside them could finish at a later time.

Solution

I have no idea of when the prop is available in the child component, so my proposed solution is to watch it, and run that watcher only once

watch: {
  prop(new, old) {
      if (old === undefined && new !== undefined) {
        console.log(this.prop)
      }
    },
  },

now, the output would give you the prop.

36