JAVASCRIPT
Custom Composable for Asynchronous Data Fetching in Vue 3
Create a reusable Vue 3 composable to encapsulate asynchronous data fetching logic, providing reactive loading, error, and data states for any API request.
// composables/useFetch.js
import { ref, isRef, unref, watchEffect } 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;
data.value = null;
// unref() to get the raw value of a ref
const urlValue = unref(url);
try {
const res = await fetch(urlValue);
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;
}
}
if (isRef(url)) {
// setup reactive re-fetch if url is a ref
watchEffect(doFetch);
} else {
// otherwise, just fetch once
doFetch();
}
return { data, error, loading, refetch: doFetch };
}
// src/App.vue (or any component)
<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="refetch">Refetch Posts</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useFetch } from './composables/useFetch';
const postId = ref(1);
const url = ref(`https://jsonplaceholder.typicode.com/posts?_limit=5`);
// Example usage with a reactive URL
const { data, error, loading, refetch } = useFetch(url);
// You could also change the URL reactively:
// setTimeout(() => {
// url.value = 'https://jsonplaceholder.typicode.com/posts?_limit=10';
// }, 3000);
</script>
How it works: This composable `useFetch` abstracts away the common pattern of fetching data, managing loading states, and handling errors. It takes a URL (which can be a reactive ref) and returns `data`, `error`, and `loading` reactive references. If the URL is reactive, `watchEffect` automatically re-fetches data when the URL changes. The `refetch` function provides a way to manually trigger a re-fetch, making this a highly flexible solution for data retrieval.