kodingup.camp

Beranda/Various Library Mastery

Konfigurasi Request dengan Axios

Modul 7 dari 134 menit bacaRequest Configuration Fundamentals

Isi modul

    Kenapa ini penting

    Sejauh ini kita memakai fetch bawaan browser. fetch bagus, tapi untuk aplikasi yang memanggil puluhan endpoint, ada hal yang terus diulang: menulis URL lengkap, menambah header Content-Type, JSON.stringify body, cek res.ok, lalu res.json(). Lupa satu langkah, bug muncul.

    axios adalah HTTP client yang paling banyak dipakai di ekosistem JavaScript. Ia mengurus konversi JSON otomatis, melempar error untuk status 4xx/5xx, mendukung timeout, dan punya fitur instance dan interceptor yang akan kita pakai di dua modul berikutnya. Versi yang dipakai: axios 1.20.0.

    Konsep inti

    Analogi: kurir langganan

    fetch itu seperti kamu mengantar paket sendiri: harus bungkus sendiri, tulis alamat lengkap, cek sendiri apakah paket sampai. axios itu seperti kurir langganan yang sudah tahu alamat kantormu (baseURL), otomatis membungkus paket (JSON), dan langsung lapor kalau paket ditolak penerima (error 4xx/5xx).

    Instalasi dan request pertama

    npm install axios
    
    import axios from "axios";
    
    const res = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
    console.log(res.data); // → { userId: 1, id: 1, title: "delectus aut autem", completed: false }
    

    Objek respons axios berisi:

    Properti Isi
    data Body respons yang sudah di-parse dari JSON
    status Kode status HTTP, misalnya 200 atau 201
    statusText Teks status
    headers Header respons
    config Konfigurasi yang dipakai untuk request ini

    Instance dan baseURL

    Daripada menulis URL lengkap setiap kali, buat instance dengan konfigurasi default:

    const api = axios.create({
      baseURL: "https://jsonplaceholder.typicode.com",
      timeout: 10000, // milidetik
      headers: { Accept: "application/json" },
    });
    
    await api.get("/todos"); // → GET https://jsonplaceholder.typicode.com/todos
    

    Instance juga membuatmu bisa punya beberapa konfigurasi berbeda, misalnya satu untuk API utama dan satu untuk layanan upload.

    Empat method utama

    Method Kegunaan Penulisan axios
    GET Ambil data api.get(url, config)
    POST Buat data baru api.post(url, data, config)
    PUT / PATCH Ganti seluruh / sebagian data api.put(url, data) / api.patch(url, data)
    DELETE Hapus data api.delete(url, config)

    Perhatikan posisi argumen: untuk post, put, dan patch, argumen kedua adalah body, argumen ketiga adalah config. Untuk get dan delete, argumen kedua langsung config.

    params: query string tanpa repot

    api.get("/todos", { params: { userId: 1, _limit: 5 } });
    // → GET /todos?userId=1&_limit=5
    

    axios merangkai dan meng-encode query string untukmu, termasuk karakter khusus seperti spasi.

    headers per request

    api.post("/todos", { title: "Baru" }, { headers: { "X-Request-Source": "dashboard" } });
    

    Header di sini digabung dengan header default instance.

    Perbandingan dengan fetch

    Aspek fetch axios
    Instalasi Bawaan browser npm install axios
    Parse JSON Manual res.json() Otomatis di res.data
    Kirim JSON Manual JSON.stringify + header Otomatis dari object
    Error 404/500 Tidak melempar, cek res.ok Otomatis melempar error
    Timeout Lewat AbortSignal.timeout(ms) Opsi timeout
    Interceptor Tidak ada Ada (request & response)
    Base URL Tidak ada axios.create({ baseURL })
    Ukuran 0 KB Belasan KB (gzip)

    fetch tetap pilihan bagus untuk proyek kecil atau saat ukuran bundle sangat penting. axios unggul ketika banyak endpoint membutuhkan konfigurasi yang sama.

    Membaca status HTTP

    Saat memakai API, kamu akan terus bertemu kode status. Kelompok besarnya:

    Kelompok Arti Contoh
    2xx Berhasil 200 OK, 201 Created, 204 No Content
    3xx Dialihkan 301, 304 Not Modified
    4xx Kesalahan dari sisi pengirim (client) 400, 401, 403, 404, 422
    5xx Kesalahan di server 500, 502, 503

    axios menganggap semua di luar 2xx sebagai error (bisa diubah lewat opsi validateStatus, tapi jarang perlu). Contoh nyata: saat kamu mengirim form daftar dengan email yang sudah terpakai, banyak API membalas 409 atau 422 beserta pesan. Dengan axios, pesan itu ada di error.response.data, dan modul berikutnya membahas cara menampilkannya dengan rapi.

    Contoh kode

    // src/lib/todoService.js, semua operasi CRUD tugas
    import axios from "axios";
    
    const api = axios.create({
      baseURL: "https://jsonplaceholder.typicode.com",
      timeout: 10000,
    });
    
    // GET dengan params
    export async function getTodos({ userId, limit = 5 } = {}) {
      const res = await api.get("/todos", { params: { userId, _limit: limit } });
      return res.data;
    }
    
    // GET satu item
    export async function getTodo(id) {
      const { data } = await api.get(`/todos/${id}`);
      return data;
    }
    
    // POST: argumen kedua = body (object biasa, axios mengubah ke JSON)
    export async function createTodo(todo) {
      const { data } = await api.post("/todos", todo);
      return data;
    }
    
    // PUT: ganti seluruh data
    export async function replaceTodo(id, todo) {
      const { data } = await api.put(`/todos/${id}`, todo);
      return data;
    }
    
    // PATCH: ubah sebagian
    export async function updateTodo(id, perubahan) {
      const { data } = await api.patch(`/todos/${id}`, perubahan);
      return data;
    }
    
    // DELETE
    export async function deleteTodo(id) {
      await api.delete(`/todos/${id}`);
    }
    
    // src/Demo.jsx, mencoba service dengan tombol
    import { useState } from "react";
    import { createTodo, getTodos, updateTodo } from "./lib/todoService";
    
    export default function Demo() {
      const [log, setLog] = useState("");
    
      async function jalankan(aksi) {
        try {
          const hasil = await aksi();
          setLog(JSON.stringify(hasil, null, 2));
        } catch (err) {
          setLog(`Error: ${err.message}`);
        }
      }
    
      return (
        <div className="space-y-2 p-6">
          <button onClick={() => jalankan(() => getTodos({ userId: 1, limit: 2 }))}>GET</button>
          <button onClick={() => jalankan(() => createTodo({ title: "Belajar axios", completed: false, userId: 1 }))}>
            POST
          </button>
          <button onClick={() => jalankan(() => updateTodo(1, { completed: true }))}>PATCH</button>
          <pre className="rounded bg-slate-100 p-3 text-sm">{log}</pre>
        </div>
      );
    }
    // → GET:   [{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false }, {...}]
    // → POST:  { "title": "Belajar axios", "completed": false, "userId": 1, "id": 201 }
    // → PATCH: { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": true }
    

    Sebagai perbandingan, ini createTodo versi fetch:

    export async function createTodoFetch(todo) {
      const res = await fetch("https://jsonplaceholder.typicode.com/todos", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(todo),
        signal: AbortSignal.timeout(10000),
      });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      return res.json();
    }
    

    Kesalahan umum

    Latihan

    1. Mudah, Buat instance api dengan baseURL jsonplaceholder, lalu ambil /users dan tampilkan nama-namanya di console.
    2. Sedang, Tulis fungsi searchPosts(userId, limit) yang memakai params untuk mengambil post milik user tertentu dengan batas jumlah.
    3. Menantang, Tulis ulang todoService dengan fetch murni (tanpa axios) tapi tetap punya baseURL, timeout, dan lempar error untuk status bukan 2xx. Bandingkan jumlah barisnya.
    Lihat solusi
    // 1.
    import axios from "axios";
    const api = axios.create({ baseURL: "https://jsonplaceholder.typicode.com" });
    const { data } = await api.get("/users");
    console.log(data.map((u) => u.name));
    // → ["Leanne Graham", "Ervin Howell", ...] (10 nama)
    
    // 2.
    export async function searchPosts(userId, limit = 3) {
      const { data } = await api.get("/posts", { params: { userId, _limit: limit } });
      return data;
    }
    // searchPosts(2, 3) → 3 post milik userId 2
    
    // 3. Versi fetch
    const BASE = "https://jsonplaceholder.typicode.com";
    
    async function request(path, { method = "GET", body, params } = {}) {
      const url = new URL(BASE + path);
      if (params) {
        Object.entries(params).forEach(([k, v]) => v !== undefined && url.searchParams.set(k, v));
      }
      const res = await fetch(url, {
        method,
        headers: body ? { "Content-Type": "application/json" } : undefined,
        body: body ? JSON.stringify(body) : undefined,
        signal: AbortSignal.timeout(10000),
      });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      return res.status === 204 ? null : res.json();
    }
    
    export const getTodos = (userId) => request("/todos", { params: { userId, _limit: 5 } });
    export const createTodo = (todo) => request("/todos", { method: "POST", body: todo });
    // Lebih panjang karena kita menulis ulang fitur yang sudah ada di axios.
    

    Ringkasan

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.