JAVASCRIPT
Managing Async Data with Loading and Error States in Vue 3 Composables
Learn to create a reusable Vue 3 Composition API composable for fetching asynchronous data, automatically handling loading, error, and success states across components.
// src/composables/useAsyncData.js
import { ref } from 'vue';
export function useAsyncData(fetcher) {
const data = ref(null);
const loading = ref(true);
const error = ref(null);
const fetchData = async (...args) => {
loading.value = true;
error.value = null;
try {
data.value = await fetcher(...args);
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
};
// Initial fetch or expose for manual trigger
fetchData();
return { data, loading, error, fetchData };
}
// src/components/MyComponent.vue
<template>
<div>
<div v-if="loading">Loading data...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<div v-else>
<h2>Data Loaded:</h2>
<pre>{{ data }}</pre>
<button @click="fetchData">Refresh Data</button>
</div>
</div>
</template>
<script setup>
import { useAsyncData } from '@/composables/useAsyncData';
const fetchDataFunction = async () => {
// Simulate an API call
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.3) { // 70% success rate
resolve({ message: 'Hello from API!', timestamp: Date.now() });
} else {
reject(new Error('Failed to fetch data!'));
}
}, 1500);
});
};
const { data, loading, error, fetchData } = useAsyncData(fetchDataFunction);
</script>
How it works: This composable, `useAsyncData`, abstracts the common pattern of fetching asynchronous data and managing its loading, error, and success states. It uses Vue's `ref` to create reactive variables for `data`, `loading`, and `error`. The `fetchData` function executes the provided `fetcher` callback, updating the reactive states accordingly. Components can then easily consume this composable to display appropriate UI based on the data's fetch status, enhancing user experience.