Search code examples
javascriptvue.jsvuejs3vue-component

In Vue3 how to transfer async data to the child component


I am trying to transfer async data from a parent file to a child component. It is currently giving error in the child component as the parent loads the data in the onMounted event. What is the correct way to do this?

Parent:

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import TestForm from '../components/TestForm.vue';

const testMe = ref();
// testMe.value = {
//   id: 1,
//   startDateTime: '2023-06-26T09:43:32.203Z',
// };

onMounted(() => {
  const newObject2 = fetchData();
  console.log('onMounted testing newObject2', newObject2);
  testMe.value = newObject2;
});

async function fetchData() {
  const res = await fetch('http://localhost:4000/testMes');
  const data = await res.json();
  const newObject = data[0];
  console.log('testing the async function data from json:', newObject);
  return newObject;
}
</script>

<template>
  <div>
    <TestForm :testProps="testMe" />
  </div>
</template>

Child: TestForm.vue

<script setup lang="ts">
import { ref } from 'vue';

const props = defineProps(['testProps']);

const startDateTime = ref('');

// eslint-disable-next-line vue/no-setup-props-destructure
startDateTime.value = props.testProps.startDateTime;
</script>

<template>
  <div>
    {{ startDateTime }}
  </div>
</template>

I am getting the error:

TypeError: Cannot read properties of undefined (reading 'startDateTime')

which I think I understand why, but what is the right way to transfer these values to the child?


Solution

  • Get data

    Since fetchData() is an asynchronous function and we don't know when it will finish, you need to add the instruction to wait for the newObject2 variable to receive the result of the fetchData() function. The instruction you should use is await.

    onMounted(async () => {
      testMe.value = await fetchData(); // here
    });
    

    Transfer to child component (prop)

    startDateTime.value = props.testProps.startDateTime;
    

    This line is executed during component initialization and only assigns the value of testProps.startDateTime to the startDateTime reference once. This means that startDateTime will not be automatically updated when testMe changes in the parent component.

    To make testProps update with changes to the testMe variable, the child component needs to watch testProps and react to its changes. For this purpose, the onUpdated lifecycle hook should be used in the child component.

    const props = defineProps(['testProps']);
    
    const startDateTime = ref('');
    
    onUpdated(() => {
      startDateTime.value = props.testProps.startDateTime;
    });