JAVASCRIPT
Reusable Data Fetching Composable with Loading and Error States
Create a robust Vue 3 Composition API composable for fetching asynchronous data, managing loading and error states across multiple components efficiently.
// src/composables/useFetch.js
import { ref, onMounted, toValue } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(true);
async function fetchData() {
loading.value = true;
error.value = null;
try {
const res = await fetch(toValue(url));
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
data.value = await res.json();
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
}
onMounted(() => {
fetchData();
});
return { data, error, loading, refetch: fetchData };
}
// src/components/DataFetcher.vue
<template>
<div>
<h1>User Data</h1>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<div v-else>
<pre>{{ JSON.stringify(data, null, 2) }}</pre>
<button @click="refetch">Refetch Data</button>
</div>
</div>
</template>
<script setup>
import { useFetch } from '@/composables/useFetch';
const { data, error, loading, refetch } = useFetch('https://jsonplaceholder.typicode.com/users/1');
</script>
How it works: This snippet demonstrates creating a reusable `useFetch` composable in Vue 3's Composition API. It encapsulates data fetching logic, including managing `loading` and `error` states using `ref`. The `onMounted` hook triggers the initial fetch, and `toValue` ensures that the URL can be either a ref or a static string. The component then consumes this composable, rendering different UI states based on the returned `data`, `error`, and `loading` reactive variables, also providing a `refetch` function.