JAVASCRIPT
Creating Reusable Async Data Fetching Logic with Vue 3 Composables
Learn to build powerful, reusable data fetching logic in Vue 3 using composable functions, managing loading states and errors efficiently for cleaner components.
// useFetch.js
import { ref, onMounted, toRefs } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(true);
const fetchData = async () => {
loading.value = true;
error.value = null;
try {
const res = await fetch(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 as refs for destructuring in components while maintaining reactivity
return { ...toRefs({ data, error, loading }), fetchData };
}
// Component usage (e.g., MyComponent.vue)
<template>
<div>
<h1>Posts</h1>
<p v-if="loading">Loading posts...</p>
<p v-if="error">Error: {{ error.message }}</p>
<ul v-if="data">
<li v-for="post in data" :key="post.id">{{ post.title }}</li>
</ul>
<button @click="fetchData" :disabled="loading">Refresh Data</button>
</div>
</template>
<script setup>
import { useFetch } from './useFetch';
const { data, error, loading, fetchData } = useFetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
</script>
How it works: This snippet demonstrates a Vue 3 Composable function (`useFetch`) for encapsulating asynchronous data fetching logic. It leverages `ref` for reactive state (data, error, loading) and `onMounted` to trigger the fetch when the component mounts. The `fetchData` function handles the API call, error handling, and updates the loading state. By returning the reactive variables and the `fetchData` function, components can easily reuse this logic, destructure the returned values, and even trigger refetches, leading to cleaner, more modular code.