JAVASCRIPT
Create a Reusable Data Fetching Composable
Build a custom Vue 3 Composition API composable (`useFetch`) to encapsulate data fetching logic, including loading and error states, for reuse across components, simplifying API calls.
// src/composables/useFetch.js
import { ref, onMounted, toValue } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const isLoading = ref(true);
async function doFetch() {
isLoading.value = true;
error.value = null;
try {
const response = await fetch(toValue(url));
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
data.value = await response.json();
} catch (err) {
error.value = err.message || 'An unknown error occurred.';
} finally {
isLoading.value = false;
}
}
onMounted(() => {
doFetch();
});
return { data, error, isLoading, doFetch };
}
// src/App.vue (Usage)
<template>
<div>
<h1>Data Fetching Composable Example</h1>
<button @click="doFetch" :disabled="isLoading">Refetch Data</button>
<div v-if="isLoading">
<p>Loading posts...</p>
</div>
<div v-else-if="error">
<p style="color: red;">Error: {{ error }}</p>
</div>
<div v-else>
<h2>Posts</h2>
<ul>
<li v-for="post in data.slice(0, 5)" :key="post.id">
<strong>{{ post.title }}</strong>
<p>{{ post.body.substring(0, 50) }}...</p>
</li>
</ul>
</div>
</div>
</template>
<script setup>
import { useFetch } from './composables/useFetch';
const { data, error, isLoading, doFetch } = useFetch('https://jsonplaceholder.typicode.com/posts');
// Optionally, react to changes in a reactive URL or trigger refetch
// watch(someReactiveUrl, doFetch);
</script>
How it works: This snippet provides a `useFetch` composable for Vue 3 that encapsulates asynchronous data fetching logic. It manages `data`, `error`, and `isLoading` reactive states, making it easy to display UI feedback during different stages of a request. The `onMounted` hook triggers the initial fetch, and a `doFetch` function is returned to allow manual refetching. `toValue` ensures that the URL can be either a static string or a reactive ref/computed property. This composable promotes reusability and keeps component logic clean by abstracting away common data fetching patterns.