JAVASCRIPT
Vue 3 Reusable Data Fetching Composable
Build a custom Vue 3 Composition API composable for fetching data from an API, providing reactive loading, error, and data states for any component that uses it.
// src/composables/useFetch.js
import { ref, onMounted, watchEffect } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(true);
const fetchData = async () => {
loading.value = true;
data.value = null;
error.value = null;
try {
const res = await fetch(url.value || url); // Handle ref or string 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;
}
};
// If url is a ref, re-fetch when it changes
if (typeof url === 'object' && url.value !== undefined) {
watchEffect(fetchData);
} else {
onMounted(fetchData); // Otherwise, fetch once on mount
}
return { data, error, loading };
}
// src/components/DataFetcher.vue
<template>
<div>
<h2>Fetched Data:</h2>
<div v-if="loading">Loading posts...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<div v-else-if="data">
<h3>Post Title: {{ data.title }}</h3>
<p>{{ data.body }}</p>
</div>
</div>
</template>
<script setup>
import { useFetch } from '../composables/useFetch';
import { ref } from 'vue';
// Example with a static URL
const { data, error, loading } = useFetch('https://jsonplaceholder.typicode.com/posts/1');
// Example with a reactive URL (uncomment to test)
// const postId = ref(1);
// const postUrl = computed(() => `https://jsonplaceholder.typicode.com/posts/${postId.value}`);
// const { data, error, loading } = useFetch(postUrl);
//
// setTimeout(() => {
// postId.value = 2; // Change post ID after 3 seconds
// }, 3000);
</script>
How it works: This snippet demonstrates a `useFetch` composable that encapsulates API data fetching logic, providing reactive `data`, `error`, and `loading` states. Components can easily reuse this composable to fetch data, handle different states, and display information. It supports both static URLs and reactive URLs (Vue refs) for dynamic fetching.