JAVASCRIPT

Vue 3 Suspense for Asynchronous Component Loading

Optimize user experience by implementing Vue 3's `Suspense` component to gracefully handle loading states for asynchronous components with fallback content.

// components/AsyncDataDisplay.vue
<template>
  <div class="async-data-container">
    <h3>Loaded Data</h3>
    <p v-if="data">{{ data.value }}</p>
    <p v-else>No data loaded yet.</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// Simulate an async operation
const data = ref(null);
await new Promise(resolve => {
  setTimeout(() => {
    data.value = 'Data successfully loaded after 2 seconds!';
    resolve();
  }, 2000);
});
</script>

<style scoped>
.async-data-container {
  border: 1px dashed #ccc;
  padding: 15px;
  margin-top: 20px;
  background-color: #f9f9f9;
}
</style>

// App.vue (Parent Component)
<template>
  <div>
    <h1>Welcome to My App</h1>
    <p>This is some content above the async component.</p>

    <!-- Using Suspense to handle the loading state of AsyncDataDisplay -->
    <Suspense>
      <!-- Content to display once AsyncDataDisplay is resolved -->
      <template #default>
        <AsyncDataDisplay />
      </template>

      <!-- Content to display while AsyncDataDisplay is pending (e.g., loading spinner) -->
      <template #fallback>
        <div class="loading-state">
          <p>Loading async data, please wait...</p>
          <div class="spinner"></div>
        </div>
      </template>
    </Suspense>

    <p style="margin-top: 20px;">This is some content below the async component.</p>
  </div>
</template>

<script setup>
import { defineAsyncComponent } from 'vue';

// Define the component as an async component
const AsyncDataDisplay = defineAsyncComponent(() =>
  import('./components/AsyncDataDisplay.vue')
);
</script>

<style>
.loading-state {
  padding: 15px;
  border: 1px solid #ddd;
  background-color: #eef;
  margin-top: 20px;
  text-align: center;
}
.spinner {
  border: 4px solid rgba(0, 0, 0, 0.1);
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border-left-color: #09f;
  animation: spin 1s ease infinite;
  margin: 10px auto;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}
</style>
How it works: This snippet demonstrates Vue 3's `Suspense` component for managing asynchronous component loading and their loading states. `AsyncDataDisplay.vue` is an asynchronous component that uses `await` in its `setup` function to simulate a data fetching delay. The parent `App.vue` wraps this async component with `<Suspense>`, using the `#default` slot for the component once it's resolved, and the `#fallback` slot to display loading content (e.g., a spinner) while the async component is pending. This provides a clean way to handle loading UI for parts of your application that depend on asynchronous operations, improving user experience.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs