JAVASCRIPT
Creating a Reusable Composable for Async Data Fetching in Vue 3
Learn to build a custom Vue 3 composable for abstracting asynchronous data fetching logic, making your components cleaner and promoting code reusability.
// composables/useFetch.js
import { ref, onMounted, toValue } from 'vue';
export function useFetch(urlRef) {
const data = ref(null);
const error = ref(null);
const loading = ref(true);
async function doFetch() {
loading.value = true;
error.value = null;
data.value = null; // Clear previous data
try {
const response = await fetch(toValue(urlRef));
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
data.value = await response.json();
} catch (e) {
error.value = e;
} finally {
loading.value = false;
}
}
onMounted(() => {
doFetch();
});
// Optionally, add a watcher if urlRef is reactive and you want to refetch on change
// import { watch } from 'vue';
// watch(urlRef, doFetch, { deep: true });
return { data, error, loading, refetch: doFetch };
}
// SomeComponent.vue
<template>
<div>
<h1>User Data</h1>
<p v-if="loading">Loading user data...</p>
<p v-else-if="error">Error: {{ error.message }}</p>
<div v-else-if="data">
<p>Name: {{ data.name }}</p>
<p>Email: {{ data.email }}</p>
<button @click="refetch">Refetch Data</button>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useFetch } from './composables/useFetch';
const userId = ref(1); // Example reactive URL part
const userUrl = ref(`https://jsonplaceholder.typicode.com/users/${userId.value}`);
// In a real app, userUrl might be a computed property based on userId
// const userUrl = computed(() => `https://jsonplaceholder.typicode.com/users/${userId.value}`);
const { data, error, loading, refetch } = useFetch(userUrl);
// To change user dynamically (example)
// setTimeout(() => {
// userId.value = 2; // This would require the watch in useFetch to trigger refetch
// userUrl.value = `https://jsonplaceholder.typicode.com/users/${userId.value}`;
// }, 3000);
</script>
How it works: This snippet demonstrates how to create a custom Vue 3 composable, `useFetch`, for encapsulating asynchronous data fetching logic. The composable manages loading, error, and data states using `ref`. It performs a fetch request when the component mounts (`onMounted`) and returns reactive references to `data`, `error`, `loading`, and a `refetch` function. The component then simply calls `useFetch` to integrate this logic, keeping its template clean and its script focused on component-specific concerns, promoting reusability across different parts of the application.