JAVASCRIPT

Creating a Reusable Vue 3 Composable for Fetching Data

Discover how to build a custom Composition API function (composable) in Vue 3 to encapsulate and reuse data fetching logic across multiple components.

// src/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() {
    // reset state before fetching..
    data.value = null;
    error.value = null;
    loading.value = true;

    // resolve the url value if it is 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 (e) {
      error.value = e;
    } 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, doFetch };
}

// src/App.vue (example usage)
<template>
  <div>
    <h1>User List</h1>
    <p v-if="loading">Loading users...</p>
    <p v-else-if="error">Error: {{ error.message }}</p>
    <ul v-else-if="data">
      <li v-for="user in data" :key="user.id">{{ user.name }} ({{ user.email }})</li>
    </ul>
    <button @click="refreshUsers">Refresh Users</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { useFetch } from './composables/useFetch';

const userId = ref(1);
const usersUrl = ref('https://jsonplaceholder.typicode.com/users');
// Example of using a reactive URL
// const userDetailUrl = computed(() => `https://jsonplaceholder.typicode.com/users/${userId.value}`);

const { data, error, loading, doFetch: refreshUsers } = useFetch(usersUrl);

// You could also use the composable with a static URL
// const { data: posts, error: postsError, loading: postsLoading } = useFetch('https://jsonplaceholder.typicode.com/posts');

// Example of changing the URL reactivity
// setTimeout(() => { userId.value = 2; }, 3000);
</script>
How it works: This snippet defines `useFetch`, a custom composable (Composition API function) for fetching data from an API. It encapsulates reactive state (`data`, `error`, `loading`) and the `doFetch` logic. The `unref` utility ensures that if the `url` argument is a ref, its value is accessed. `watchEffect` is used to automatically re-run `doFetch` whenever the `url` (if it's a ref) changes, making the composable reactive. This pattern promotes code reuse, cleaner components, and better separation of concerns.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs