JAVASCRIPT
Reusable Data Fetching Composable in Vue 3
Create a custom composable function in Vue 3 to encapsulate data fetching logic, making it reusable, reactive, and easy to integrate into any component that needs to fetch data.
// useFetch.js
import { ref, onMounted, toValue } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(true);
async function fetchData() {
loading.value = true;
error.value = null;
data.value = null;
try {
// toValue ensures that if url is a ref, its value is extracted
const res = await fetch(toValue(url));
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;
}
}
// Fetch data on component mount by default
onMounted(() => fetchData());
return { data, error, loading, fetchData };
}
<!-- ComponentUsingFetch.vue -->
<template>
<div>
<h1>Data from API</h1>
<p v-if="loading">Loading...</p>
<p v-else-if="error">Error: {{ error.message }}</p>
<pre v-else>{{ data }}</pre>
<button @click="fetchData">Refresh Data</button>
</div>
</template>
<script setup>
import { useFetch } from './useFetch'; // Assuming useFetch.js is in the same directory
const { data, error, loading, fetchData } = useFetch('https://jsonplaceholder.typicode.com/todos/1');
// Example of using a reactive URL:
// import { ref, watch } from 'vue';
// const userId = ref(1);
// const { data, error, loading } = useFetch(() => `https://jsonplaceholder.typicode.com/users/${userId.value}`);
// watch(userId, () => { /* data will automatically refetch if the composable watches its arguments,
// which it does here by using toValue on url argument inside fetchData. */ });
</script>
How it works: This snippet provides a reusable data fetching composable (`useFetch`) for Vue 3. Composables are functions that encapsulate stateful logic and can be reused across components, promoting better organization and reusability. The `useFetch` composable handles the loading state, potential errors, and the fetched data itself, exposing them as reactive `ref`s. It automatically fetches data when the component mounts and includes a `fetchData` function for manual refresh. Using `toValue(url)` allows the URL parameter to be either a static string or a reactive `ref`, enabling dynamic API calls.