JAVASCRIPT
Creating a Reusable Vue 3 Composable for Data Fetching
Learn to build a powerful and reusable data fetching composable in Vue 3 using the Composition API, `ref`, and lifecycle hooks for clean asynchronous data management.
// composables/useFetch.js
import { ref, onMounted, watch } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(true);
async function doFetch() {
loading.value = true;
error.value = null;
try {
const res = await fetch(url.value || url); // Handle ref or direct string
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
data.value = await res.json();
} catch (e) {
error.value = e;
} finally {
loading.value = false;
}
}
onMounted(() => {
doFetch();
});
// Re-fetch if the URL changes (if it's a ref)
if (typeof url === 'object' && url !== null && 'value' in url) {
watch(url, doFetch);
}
return { data, error, loading, doFetch };
}
// components/MyComponent.vue
<template>
<div>
<div v-if="loading">Loading posts...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<ul v-else>
<li v-for="post in data" :key="post.id">{{ post.title }}</li>
</ul>
<button @click="refreshData">Refresh</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useFetch } from '../composables/useFetch';
const postId = ref(1); // Example dynamic URL part
const apiUrl = ref(`https://jsonplaceholder.typicode.com/posts?_limit=5`); // Can be dynamic
// Using the composable
const { data, error, loading, doFetch: refreshData } = useFetch(apiUrl);
// Example of changing the URL to trigger re-fetch (if apiUrl was reactive)
// setTimeout(() => {
// apiUrl.value = 'https://jsonplaceholder.typicode.com/todos?_limit=3';
// }, 5000);
</script>
How it works: This snippet demonstrates creating a reusable `useFetch` composable in Vue 3's Composition API. It encapsulates data fetching logic, providing reactive `data`, `error`, and `loading` states. The `onMounted` hook initiates the fetch operation, and importantly, it uses a `watch` effect to automatically re-fetch data if the provided URL (when passed as a `ref`) changes. This pattern promotes clean, reusable, and testable code for asynchronous operations within your Vue applications, making it easy to integrate data fetching into any component.