Learn Vue - Data Fetching & Asynchronous UI
Series/Learn Vue/Episode 8
Episode 8 of 24

Learn Vue - Data Fetching & Asynchronous UI

This episode covers fetching data in Vue applications: using fetch and Axios, managing loading state and error handling, fetching patterns with the Composition API and composables, plus integrating Vue Query (TanStack Query) for caching and server state synchronization.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Almost every real application fetches data from a server: product lists, user profiles, notifications. This is where the interface becomes asynchronous — and the most common mistake isn't in the data logic, but in how loading and errors are handled.

Episode 8 covers fetching data with fetch and Axios, organizing loading state and error handling, designing fetching patterns with the Composition API, then introducing Vue Query (TanStack Query) for caching and server state synchronization. After this episode, you'll be able to build UIs that load data confidently and elegantly.

Data Fetching with fetch and Axios

fetch: The Browser's Built-in API

fetch is available in all modern browsers without any extra dependency:

JSFetch dasar
async function ambilProduk() {
  const res = await fetch("/api/produk");
  if (!res.ok) {
    throw new Error("Gagal memuat produk");
  }
  return res.json();
}

fetch("/api/produk") returns a promise; res.ok indicates a successful HTTP response, and res.json() parses the body into a JavaScript object. Always check res.ok because fetch doesn't throw an error on 4xx/5xx statuses.

Axios: A Complete HTTP Client

Axios offers interceptors, timeouts, and automatic JSON conversion:

Install Axios
npm install axios
JSAxios dasar
import axios from "axios";
 
const { data } = await axios.get("/api/produk", { timeout: 5000 });

axios.get("/api/produk", { timeout: 5000 }) throws an error automatically on any status other than 2xx and parses JSON straight into data. Use Axios when you need interceptors for auth headers or logging — we'll use it in episodes 12 and 13.

Loading State and Error Handling

The Three-State Pattern

Every fetching operation has three states: loading, success, and error. Manage all three explicitly:

JSPattern loading dan error
<script setup>
import { ref } from "vue";
 
const data = ref(null);
const loading = ref(true);
const error = ref(null);
 
async function muat() {
  loading.value = true;
  error.value = null;
  try {
    const res = await fetch("/api/produk");
    if (!res.ok) throw new Error("Server error");
    data.value = await res.json();
  } catch (e) {
    error.value = e.message;
  } finally {
    loading.value = false;
  }
}
 
muat();
</script>
 
<template>
  <div v-if="loading">Memuat data...</div>
  <div v-else-if="error">Terjadi error: {{ error }}</div>
  <ul v-else>
    <li v-for="item in data" :key="item.id">{{ item.nama }}</li>
  </ul>
</template>

v-if="loading", v-else-if="error", and v-else present the three states without confusion. finally guarantees loading is always turned off, even on error.

Fetching Patterns with the Composition API

Wrapping Fetching into a Composable

To make fetching logic reusable, wrap it into a useFetch composable:

JSComposable useFetch
import { ref } from "vue";
 
export function useFetch(url) {
  const data = ref(null);
  const loading = ref(true);
  const error = ref(null);
 
  async function jalankan() {
    try {
      const res = await fetch(url);
      data.value = await res.json();
    } catch (e) {
      error.value = e.message;
    } finally {
      loading.value = false;
    }
  }
 
  jalankan();
  return { data, loading, error, jalankan };
}

useFetch("/api/produk") starts fetching immediately when called in setup and returns three refs plus a reload function. Components just consume the result — this pattern is the foundation for TanStack Query integration.

Integrating Vue Query (TanStack Query)

Install and Setup

Vue Query, now called TanStack Query, manages server state with caching, retries, and automatic invalidation:

Install TanStack Query
npm install @tanstack/vue-query

Using useQuery

JSuseQuery di komponen
import { useQuery } from "@tanstack/vue-query";
 
const { data, isPending, isError, error, refetch } = useQuery({
  queryKey: ["produk"],
  queryFn: () => fetch("/api/produk").then((r) => r.json()),
});

useQuery({ queryKey: ["produk"], queryFn: ... }) fetches the data, stores it in the cache under the key ["produk"], and automatically provides isPending, isError, error, and refetch. The same query isn't refetched unnecessarily — that's the caching you get for free.

Cache Invalidation

When data changes, tell TanStack Query to fetch again:

JSInvalidasi query
import { useQueryClient } from "@tanstack/vue-query";
 
const queryClient = useQueryClient();
 
async function simpan(data) {
  await fetch("/api/produk", { method: "POST", body: JSON.stringify(data) });
  queryClient.invalidateQueries({ queryKey: ["produk"] });
}

queryClient.invalidateQueries({ queryKey: ["produk"] }) marks the old cache stale and triggers a refetch in every component using that query. This replaces manual synchronization between components — we'll go deeper in episode 14.

Tip

Use TanStack Query for all state that comes from the server, and keep genuinely UI-local state like an open modal or a form inside refs and composables.

Summary

Episode 8 equipped you with correct data fetching: fetch and Axios as HTTP clients, the three-state pattern for loading and error handling, a useFetch composable for reusability, and TanStack Query for caching and server state invalidation.

Key takeaways:

  • Always check res.ok when using fetch.
  • Axios is useful for interceptors and timeouts.
  • Manage loading, success, and error as explicit state.
  • finally ensures loading is turned off no matter the outcome.
  • A useFetch composable makes fetching reusable.
  • TanStack Query adds automatic caching and invalidation.

In the next episode 9, we'll cover routing and navigation — Vue Router for organizing routes and components, dynamic and nested routes with lazy loading, scroll behavior and programmatic navigation, plus route meta for per-route authentication.

Learn Vue - Data Fetching & Asynchronous UI | Learn Vue