useFetch: Async Data Composable
data, loading, error refs, fetch on mount, refetch function, AbortController cleanup.
useFetch: Async Data Composable is a free Vue Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Vue Academy learning path, and your progress syncs across the web and the CoddyKit app. The Vue Academy course includes 4 lessons in total.
The useFetch Goal
Async data fetching repeats everywhere: loading flags, error handling, the request itself. useFetch bundles this into one reusable composable returning data, loading, and error.
The Three Reactive Refs
Start with three refs that describe any async request state.
import { ref } from "vue";
function useFetch(url) {
const data = ref(null);
const loading = ref(false);
const error = ref(null);
}The Fetch Routine
Write an async function that flips loading, performs the request, and stores the result. We will refine error handling next.
async function execute() {
loading.value = true;
const res = await fetch(url);
data.value = await res.json();
loading.value = false;
}try / catch / finally
Wrap the request so errors land in error and loading always resets, success or failure, in finally.
async function execute() {
loading.value = true;
error.value = null;
try {
const res = await fetch(url);
if (!res.ok) throw new Error("HTTP " + res.status);
data.value = await res.json();
} catch (e) {
error.value = e;
} finally {
loading.value = false;
}
}Fetching in onMounted
Kick off the request when the component mounts so data loads automatically.
import { onMounted } from "vue";
onMounted(execute);A refetch Function
Expose execute as refetch so consumers can reload on demand - after a mutation or a retry button.
return { data, loading, error, refetch: execute };AbortController for Cleanup
If the component unmounts mid-request, abort the fetch to avoid setting state on a dead component. Create an AbortController and pass its signal.
const controller = new AbortController();
const res = await fetch(url, { signal: controller.signal });Aborting on Unmount
Cancel the in-flight request in onUnmounted. Ignore the resulting abort error in the catch.
import { onUnmounted } from "vue";
onUnmounted(() => controller.abort());The Full useFetch
Assembled, the composable handles loading, errors, refetching, and cleanup in one tidy unit.
function useFetch(url) {
const data = ref(null);
const loading = ref(false);
const error = ref(null);
const controller = new AbortController();
async function execute() {
loading.value = true; error.value = null;
try {
const res = await fetch(url, { signal: controller.signal });
data.value = await res.json();
} catch (e) {
if (e.name !== "AbortError") error.value = e;
} finally {
loading.value = false;
}
}
onMounted(execute);
onUnmounted(() => controller.abort());
return { data, loading, error, refetch: execute };
}Using It in a Component
Consumers render based on the three refs - a spinner while loading, an error message on failure, the data otherwise.
const { data, loading, error } = useFetch("/api/posts");Template Pattern
Branch on the state in the template for a complete UX.
<p v-if="loading">Loading...</p>
<p v-else-if="error">{{ error.message }}</p>
<ul v-else>
<li v-for="p in data" :key="p.id">{{ p.title }}</li>
</ul>Quick Check
What is the role of AbortController in useFetch?
Recap
You built useFetch(url) exposing data, loading, and error refs, fetching in onMounted with a try/catch/finally pattern, a refetch function, and an AbortController cleaned up in onUnmounted.
Learn HTML with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 42
- Lessons
- 156
Frequently Asked Questions
Is the “useFetch: Async Data Composable” lesson free?
Yes — any 3 lessons of the Vue Academy learning path, including “useFetch: Async Data Composable”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Vue Academy course includes 4 lessons in total.
What will I learn in “useFetch: Async Data Composable”?
data, loading, error refs, fetch on mount, refetch function, AbortController cleanup. You practise Vue Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Vue Academy?
No prior experience is required. Vue Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.
How long does the “useFetch: Async Data Composable” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Vue Academy lesson?
Yes. Every Vue Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- What Makes a Good Composable
- useCounter: A Simple Composable
- useFetch: Async Data Composable
- VueUse: The Composable Library