0
0
Vueframework~15 mins

Composable for API calls (useFetch pattern) in Vue - Deep Dive

Choose your learning style9 modes available
Overview - Composable For Api Calls Usefetch Pattern
What is it?
A composable for API calls using the useFetch pattern in Vue is a reusable function that handles fetching data from servers. It simplifies making requests, managing loading states, and handling errors inside Vue components. This pattern helps keep your code clean and organized by separating data fetching logic from UI code. It uses Vue's Composition API to share this logic easily across components.
Why it matters
Without this pattern, every component would need to write its own code to fetch data, handle loading, and errors, leading to repeated code and bugs. This makes apps harder to maintain and slower to develop. The useFetch composable centralizes this logic, making apps more reliable and easier to update. It also improves user experience by managing loading and error states consistently.
Where it fits
Before learning this, you should understand Vue basics, especially the Composition API and reactive state. After mastering useFetch composables, you can explore advanced state management, caching strategies, and server-side rendering in Vue apps.
Mental Model
Core Idea
A useFetch composable is like a smart helper that fetches data, tracks loading and errors, and shares this logic across Vue components.
Think of it like...
Imagine ordering food at a restaurant: instead of each person going to the kitchen, you have a waiter (the composable) who takes orders, checks if the kitchen is busy (loading), and tells you if something went wrong (error). Everyone gets their food without repeating the ordering process.
┌───────────────┐
│ Vue Component │
└──────┬────────┘
       │ uses
       ▼
┌───────────────┐
│ useFetch      │
│ - fetch data  │
│ - loading     │
│ - error      │
└──────┬────────┘
       │ calls
       ▼
┌───────────────┐
│ API Server    │
└───────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Vue Composition API Basics
🤔
Concept: Learn how Vue's Composition API lets you write reusable logic with functions and reactive state.
Vue's Composition API uses functions like ref() and reactive() to create reactive data. You can write functions that return reactive data and methods, then use them inside components. This is the base for creating composables like useFetch.
Result
You can create and use reactive variables and functions inside Vue components.
Understanding reactive state and functions is essential because composables rely on these to share logic and data.
2
FoundationMaking Basic API Calls in Vue
🤔
Concept: Learn how to fetch data from an API inside a Vue component using fetch and reactive state.
Inside setup(), you can use fetch() to get data from a URL. Use ref() to store the data, loading state, and errors. Update these refs based on fetch results and errors.
Result
You can display data from an API and show loading or error messages in your component.
Knowing how to fetch data and track loading/errors manually helps you appreciate why useFetch composables simplify this.
3
IntermediateCreating a Basic useFetch Composable
🤔Before reading on: do you think a composable should return only data, or also loading and error states? Commit to your answer.
Concept: Build a reusable function that fetches data and returns reactive data, loading, and error states.
Write a function useFetch(url) that creates refs for data, loading, and error. It calls fetch with the URL, updates loading and error accordingly, and returns these refs. Components can call useFetch to get all needed info.
Result
You get a reusable function that components can use to fetch data with consistent loading and error handling.
Returning loading and error states along with data makes the composable flexible and useful for UI feedback.
4
IntermediateHandling Reactive URL Changes in useFetch
🤔Before reading on: do you think useFetch should refetch automatically if the URL changes reactively? Commit to yes or no.
Concept: Make useFetch respond to reactive URL changes by refetching data automatically.
Use Vue's watch() inside useFetch to watch the URL parameter if it's reactive. When URL changes, trigger fetch again to update data, loading, and error states.
Result
The composable updates data automatically when the URL changes, keeping UI in sync.
Watching reactive inputs inside composables enables dynamic and responsive data fetching.
5
IntermediateAdding Request Options and Abort Support
🤔
Concept: Extend useFetch to accept fetch options and support aborting requests to avoid race conditions.
Add a second parameter for fetch options like headers or method. Use AbortController to cancel previous fetch if a new one starts before completion. This prevents outdated data showing.
Result
useFetch becomes more flexible and robust, handling complex requests and avoiding bugs.
Supporting options and aborting requests is key for real-world apps where users change inputs quickly.
6
AdvancedIntegrating useFetch with Vue Suspense and Async Components
🤔Before reading on: do you think useFetch can work seamlessly with Vue's Suspense for loading states? Commit to yes or no.
Concept: Use useFetch inside async setup functions and Vue Suspense to handle loading UI declaratively.
Return a Promise from useFetch or expose a ready state. Use Vue Suspense in templates to show fallback UI while data loads. This improves user experience with smooth loading transitions.
Result
Components using useFetch can leverage Vue Suspense for better loading management.
Combining composables with Vue's built-in async features creates cleaner and more powerful UI patterns.
7
ExpertOptimizing useFetch with Caching and Shared Requests
🤔Before reading on: do you think each useFetch call always makes a new network request, or can requests be shared? Commit to your answer.
Concept: Implement caching inside useFetch to reuse data and share requests across components to reduce network load.
Use a Map or WeakMap to store ongoing and completed fetches keyed by URL and options. If a request is in progress or cached, return that instead of fetching again. This improves performance and reduces server load.
Result
Multiple components requesting the same data get it instantly or share the same network request.
Caching and request sharing inside composables is a powerful optimization often missed by beginners.
Under the Hood
useFetch creates reactive references for data, loading, and error states. It uses the browser's fetch API to request data asynchronously. Vue's reactivity system tracks these refs so components update automatically when data changes. When the URL or options change, a watcher triggers a new fetch. AbortController cancels previous requests to avoid race conditions. Internally, caching can store promises or results keyed by request parameters to share or reuse data.
Why designed this way?
This pattern was designed to separate data fetching logic from UI code, making it reusable and testable. Vue's Composition API enables this modularity. Using reactive refs and watchers fits Vue's reactive model naturally. AbortController support was added to handle real-world user interactions where requests may overlap. Caching optimizes performance and reduces redundant network calls. Alternatives like mixing fetch calls directly in components lead to duplicated code and harder maintenance.
┌───────────────┐
│ useFetch      │
│ ┌───────────┐ │
│ │ refs:     │ │
│ │ data      │ │
│ │ loading   │ │
│ │ error     │ │
│ └───────────┘ │
│ ┌───────────┐ │
│ │ fetch API │ │
│ └───────────┘ │
│ ┌───────────┐ │
│ │ watcher   │ │
│ └───────────┘ │
│ ┌───────────┐ │
│ │ AbortCtrl │ │
│ └───────────┘ │
│ ┌───────────┐ │
│ │ cache     │ │
│ └───────────┘ │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Vue Component │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does useFetch always make a new network request every time it is called? Commit to yes or no.
Common Belief:useFetch always fetches fresh data on every call, so caching is unnecessary.
Tap to reveal reality
Reality:By default, useFetch can be enhanced to cache requests and share ongoing fetches to avoid redundant network calls.
Why it matters:Without caching, apps waste bandwidth and slow down, especially when multiple components request the same data.
Quick: Is it safe to ignore aborting fetch requests in useFetch? Commit to yes or no.
Common Belief:AbortController is optional and not needed in most cases.
Tap to reveal reality
Reality:Not aborting fetches can cause race conditions where outdated data overwrites newer data, leading to UI bugs.
Why it matters:Ignoring aborts can cause confusing bugs and poor user experience when users change inputs quickly.
Quick: Can useFetch composables only be used inside setup()? Commit to yes or no.
Common Belief:useFetch must be called only inside the setup() function of Vue components.
Tap to reveal reality
Reality:useFetch can be used in any Composition API context, including other composables or async setup functions.
Why it matters:Limiting useFetch to setup() reduces flexibility and reuse in complex apps.
Quick: Does useFetch automatically handle all error types? Commit to yes or no.
Common Belief:useFetch composables catch and handle every possible error automatically.
Tap to reveal reality
Reality:useFetch handles network errors and HTTP errors if coded, but some errors like JSON parsing or logic errors need explicit handling.
Why it matters:Assuming automatic error handling can cause uncaught exceptions and app crashes.
Expert Zone
1
useFetch composables can be designed to support SSR (server-side rendering) by detecting environment and prefetching data.
2
Combining useFetch with Vue's Suspense requires careful Promise management to avoid flickering or blocking UI.
3
Caching strategies inside useFetch can be fine-tuned with expiration times, stale-while-revalidate, or manual invalidation.
When NOT to use
Avoid useFetch composables when you need complex global state management or offline support; instead, use Vuex, Pinia, or dedicated data libraries like Apollo Client for GraphQL. Also, for very simple one-off fetches, direct fetch calls may be simpler.
Production Patterns
In production, useFetch composables are often wrapped with caching layers, integrated with authentication tokens, and combined with error reporting services. They are used in combination with global state stores to sync data across components and with Suspense for smooth loading states.
Connections
Reactive Programming
useFetch builds on reactive programming principles by using reactive state and watchers.
Understanding reactive programming helps grasp how useFetch updates UI automatically when data changes.
HTTP Caching
useFetch caching strategies relate to HTTP caching concepts like cache-control and stale data.
Knowing HTTP caching helps design better caching inside useFetch to improve performance and freshness.
Event-driven Systems
useFetch reacts to changes in inputs (like URL) similar to event-driven programming.
Recognizing useFetch as an event-driven pattern clarifies how watchers trigger side effects on reactive changes.
Common Pitfalls
#1Not aborting previous fetch requests causes outdated data to overwrite newer data.
Wrong approach:function useFetch(url) { const data = ref(null); const loading = ref(false); const error = ref(null); loading.value = true; fetch(url) .then(res => res.json()) .then(json => { data.value = json; loading.value = false; }) .catch(err => { error.value = err; loading.value = false; }); return { data, loading, error }; }
Correct approach:function useFetch(url) { const data = ref(null); const loading = ref(false); const error = ref(null); const controller = new AbortController(); loading.value = true; fetch(url, { signal: controller.signal }) .then(res => res.json()) .then(json => { data.value = json; loading.value = false; }) .catch(err => { if (err.name !== 'AbortError') { error.value = err; } loading.value = false; }); // Abort previous fetch if needed return { data, loading, error, controller }; }
Root cause:Beginners often overlook that fetch requests continue even if new requests start, causing race conditions.
#2Calling useFetch with a non-reactive URL and expecting automatic updates.
Wrong approach:const { data } = useFetch('https://api.example.com/data'); // Later URL changes but useFetch does not refetch
Correct approach:const url = ref('https://api.example.com/data'); const { data } = useFetch(url); watch(url, () => { /* refetch happens automatically */ });
Root cause:Not using reactive references for inputs means Vue cannot track changes to trigger refetch.
#3Ignoring error handling and assuming fetch always succeeds.
Wrong approach:const { data } = useFetch(url); // No error or loading state used
Correct approach:const { data, error, loading } = useFetch(url); if (loading.value) showLoading(); if (error.value) showError(error.value);
Root cause:Beginners often focus only on data and forget to handle loading and error states, leading to poor UX.
Key Takeaways
useFetch composables in Vue encapsulate data fetching logic, making it reusable and clean.
They return reactive data, loading, and error states so components can reactively update UI.
Supporting reactive inputs and aborting fetches prevents bugs and keeps data fresh.
Advanced useFetch composables include caching and integration with Vue Suspense for better performance and UX.
Understanding the internal mechanism and common pitfalls helps build robust and maintainable Vue apps.