Async Methods using Composition API won't render

I’m using Ionic Vue (Ionic 6 and Vue 3) and I want to have a simple async function in my composition API to use localStorage, but making a method async breaks it, preventing it from rendering.
I get this error “studentDetails.vue?c633:26 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘0’)”.
I also this these Vue warnings: “[Vue warn]: Unhandled error during execution of render function” and runtime-core.esm-bundler.js?d2dd:38 [Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at Vue Issue Helper.

I commented out the part of the code that uses async with await to hone in my problem after it didn’t work with it, and simply taking out async and making it a normal method while leaving the first if statement works fine, but it blows up when I use async. The console.log works, but I get that error and nothing renders. I left it here to provide context and show how I’m using await later on. I’m rather confused what composition API example I can find look this simple.
I can’t find any good documentation on this and LocalStorage should work fine with Ionic Vue.

<template >
<div v-if="loadedStudent">
  <base-layout
    :pageTitle="loadedStudent ? loadedStudent.name : 'Loading...'"
    page-default-back-link="/"
  >

    <h2 v-if="!loadedStudent">could not find student with given ID</h2>
    <!-- changed it from foil to passedStudentListClassFilter -->
    <student-overview
      v-else
      :classType="loadedStudent.classTypes[classTypeFilter].class"
      :classTime="loadedStudent.classTypes[classTypeFilter].classGroupIds"
      :name="loadedStudent.name"
      :notes="loadedStudent.classTypes[classTypeFilter].notes"
    >
    </student-overview>
  </base-layout></div>
</template>
<script>
import { computed, ref } from "vue";
import { useStore } from "vuex";
import { useRoute } from "vue-router";

//imports for storage
import { Storage } from "@ionic/storage";
import studentOverview from "../components/student/studentOverview.vue";

export default {
  components: {
    studentOverview,
  },
    setup() {
        const store = useStore();
        const route = useRoute();

        const storage = new Storage();
       //await used in example, but can't use await in standard setup()
       storage.create();

        var studentId = ref(route.params.id); 

    const loadedStudent = computed(() =>
          getStudent(studentId.value)
        );
          const getStudent = async (studentId) => {
          const student = store.getters.student(studentId);

          if (student) {
            console.log("gotten from State: ", student);
            return student;
          }
          // else {
          //     const studentJson = await storage.get(studentId);
          //     const studentParsed = JSON.parse(studentJson);
          //     store.dispatch("addStudent", studentParsed);
          //     console.log("gotten from sql and added to state: ", student);
          //     return student;
          // }
      }
    }

    return { loadedStudent, classTypeFilter };
  },
};
</script>

I would try Storage Capacitor Plugin API - Capacitor (capacitorjs.com)

Sadly, there will be too much data for storage capacitor to handle it. LocalStorage is much better suited to the amount of data I’ll need to store since it will not be super lightweight, which is what storage capacitor needs.

If it is that much data, is there a reason you are not using sqlite

I’m using the SQLite plugin for local storage. That should store the data I need to be stored and fits the time and scope of what I’m doing better.

You can use async/await in onMounted();

Or in setup() by wrapping it in an IIFE


 (async () => {
   const res = await axios.get("https://jsonplaceholder.typicode.com/users");
   users.value = res.data;
   console.log(res);
 })();

I figured out the answer. I used this to get data to load. I used a v-if statement to handle the data rendering when data is ready on the template.

watchEffect(async () => {
      await storage.create();
      // const getStudent = async (studentId) => {
      const student = store.getters.student(studentId.value);
      // gets student from state in vuex if possible, otherwise looks in localstorage
      if (student) {
        console.log("gotten from State: ", student);
        displayPage.value = "true";
        loadedStudent.value = student;
      }
      else {

          const studentJson = await storage.get(studentId.value);
          const studentParsed = JSON.parse(studentJson);
          store.dispatch("addStudent", studentParsed);
          console.log("gotten from sql and added to state: ", student);
          return student;
      }

    });
1 Like