A composable for API calls helps you fetch data easily and reuse the logic in many parts of your Vue app.
Composable for API calls (useFetch pattern) in Vue
import { ref } from 'vue'; export function useFetch(url) { const data = ref(null); const error = ref(null); const loading = ref(false); async function fetchData() { loading.value = true; error.value = null; try { const response = await fetch(url); if (!response.ok) throw new Error('Network error'); data.value = await response.json(); } catch (err) { error.value = err.message; } finally { loading.value = false; } } fetchData(); return { data, error, loading, fetchData }; }
The composable returns reactive references for data, error, and loading states.
You call the fetchData function to refresh the data anytime.
const { data, error, loading } = useFetch('https://api.example.com/items');
const { data, error, loading, fetchData } = useFetch('https://api.example.com/users'); // Later in code, call fetchData() to reload
import { watch } from 'vue'; const { data, error, loading } = useFetch('https://api.example.com/posts'); watch(data, (newData) => { console.log('Data changed:', newData); });
This Vue component uses the useFetch composable to load posts from an API. It shows loading and error messages and lists post titles. The reload button lets users fetch the data again.
<template> <section aria-live="polite"> <h2>Posts</h2> <button @click="fetchData" aria-label="Reload posts">Reload</button> <p v-if="loading">Loading posts...</p> <p v-if="error" role="alert">Error: {{ error }}</p> <ul v-if="data"> <li v-for="post in data" :key="post.id">{{ post.title }}</li> </ul> </section> </template> <script setup> import { useFetch } from './useFetch'; const { data, error, loading, fetchData } = useFetch('https://jsonplaceholder.typicode.com/posts'); </script>
Always handle loading and error states to improve user experience.
Use aria-live and role="alert" for accessibility when showing dynamic messages.
Composable functions keep your code clean and easy to maintain.
A composable for API calls helps fetch and manage data reactively.
It returns data, loading, and error states you can use in your components.
You can reuse the same logic across your app by importing the composable.
Practice
useFetch in Vue?Solution
Step 1: Understand composable role
A composable in Vue is a reusable function that encapsulates logic, often for state or side effects.Step 2: Identify useFetch purpose
TheuseFetchcomposable specifically handles API calls and manages reactive states like loading and error.Final Answer:
To fetch data from an API and manage loading and error states reactively -> Option AQuick Check:
Composable useFetch = fetch + reactive states [OK]
- Confusing composables with styling or routing
- Thinking composables only handle UI rendering
- Assuming composables are Vue components
useFetch composable in a Vue component?Solution
Step 1: Check import syntax
The composable is usually exported from a file and imported with curly braces if it's a named export.Step 2: Using the composable
CallinguseFetch(url)returns reactive properties likedataanderror.Final Answer:
import { useFetch } from '@/composables/useFetch'; const { data, error } = useFetch(url); -> Option CQuick Check:
Correct import + destructure = import { useFetch } from '@/composables/useFetch'; const { data, error } = useFetch(url); [OK]
- Importing from wrong path or package
- Using default import when composable is named export
- Not destructuring returned reactive properties
useFetch composable usage:const { data, loading, error } = useFetch('https://api.example.com/items');What will
loading.value be immediately after calling useFetch?Solution
Step 1: Understand loading state in useFetch
Loading usually starts as true when the fetch begins to indicate data is being fetched.Step 2: Check initial loading value
Immediately after calling, loading is true until data or error updates it to false.Final Answer:
true -> Option BQuick Check:
Loading starts true during fetch [OK]
- Assuming loading starts false before fetch
- Confusing loading with data presence
- Expecting loading to be null or undefined
useFetch composable snippet?export function useFetch(url) {
const data = ref(null);
const loading = ref(false);
const error = ref(null);
fetch(url)
.then(res => res.json())
.then(json => { data.value = json; loading.value = false; })
.catch(err => { error.value = err; loading.value = false; });
loading.value = true;
return { data, loading, error };
}Solution
Step 1: Analyze loading state timing
Loading is set to false inside fetch callbacks but set to true after fetch starts, which can cause timing issues.Step 2: Identify race condition
Because loading is set to true after fetch call, it might overwrite loading false set in callbacks if fetch resolves quickly.Final Answer:
Setting loading.value = true after fetch call starts causes race condition -> Option AQuick Check:
Loading state timing error = Setting loading.value = true after fetch call starts causes race condition [OK]
- Setting loading true after fetch call instead of before
- Confusing async/await with promises syntax errors
- Assuming initial data type must be array
useFetch composable that automatically retries fetching up to 3 times if the API call fails. Which approach correctly adds this retry logic?Solution
Step 1: Understand retry logic needs repeated fetch calls
Retry means calling fetch again if it fails, up to a limit.Step 2: Implement retry inside composable
A recursive or loop function inside composable can retry fetch on error until max retries.Step 3: Evaluate other options
Ignoring errors or retrying outside composable breaks encapsulation; try/catch without retry misses requirement.Final Answer:
Use a recursive function inside the composable that calls fetch again on error until max retries reached -> Option DQuick Check:
Retry logic inside composable = Use a recursive function inside the composable that calls fetch again on error until max retries reached [OK]
- Retrying outside composable losing reactive state control
- Ignoring errors instead of retrying
- Not limiting retry attempts causing infinite loops
Ready to prove it?
Pass the test and this pattern moves unknown
