Tutorial Laravel 12 API Next JS 15 dan Tailwind CSS #7 Membuat Helper API Global

Belajar membangun aplikasi fullstack modern dengan backend Laravel 12 RESTful API, frontend Next.js, dan desain menggunakan Tailwind CSS. Tutorial ini membahas step-by-step mulai dari setup environment, pembuatan API, konsumsi API di Next.js, hingga integrasi UI responsif.

✅ Telah dilihat 320 kali

Rating: 5.00 ⭐

... 13 August 2025, 20:33

Membuat Helper API Global

Saat membangun aplikasi modern, kita sering perlu berkomunikasi dengan backend melalui API. Agar kode lebih rapi dan mudah dipelihara, sebaiknya kita tidak menulis fetch di setiap komponen, melainkan membuat helper API global yang bisa digunakan di seluruh aplikasi.

Di Next.js dengan TypeScript, kita bisa membuat fungsi reusable apiFetch yang menangani beberapa hal sekaligus:

  1. Base URL – URL dasar API, sehingga kita hanya perlu menuliskan endpoint relatif.
  2. Headers – otomatis menambahkan Content-Type: application/json dan custom headers lain jika diperlukan.
  3. Error Handling – jika response API gagal, helper ini akan otomatis menangkap error dan memberikan pesan yang jelas.
  4. Cache Control – cache: "no-store" memastikan data selalu fresh saat diambil.

Silakan teman-teman buat sebuah file baru kemudian letakkan didalam folder lib yang sudah ada. beri nama file baru dengan api.ts. Kemudian masukkan kode berikut ini:

project-root/
├─ lib/
│  ├─ api.ts       <-- file helper API global
│  └─ ...
export interface ApiOptions extends RequestInit {
  headers?: HeadersInit;
  signal?: AbortSignal;
}

export async function apiFetch<T>(endpoint: string, options: ApiOptions = {}): Promise<T> {
  const baseUrl = "http://127.0.0.1:8000/api";

  try {
    const res = await fetch(`${baseUrl}${endpoint}`, {
      headers: {
        "Content-Type": "application/json",
        ...options.headers,
      },
      cache: "no-store",
      ...options,
    });

    let data: any;
    try {
      data = await res.json();
    } catch {
      data = null;
    }

    if (!res.ok) {
      const errorMsg = data?.message || `${res.status} ${res.statusText}` || "API Error";
      throw new Error(errorMsg);
    }

    return data as T;
  } catch (err: any) {
    console.error("API Fetch Error:", err);
    throw new Error(err.message || "Unknown API error");
  }
}

ApiOptions interface

export interface ApiOptions extends RequestInit {
  headers?: HeadersInit;
  signal?: AbortSignal;
}
  • Tujuan: Membuat tipe data untuk opsi API yang bisa kita kirim ke apiFetch.
  • extends RequestInit → artinya semua properti standar fetch (misal method, body, mode, credentials) otomatis masuk.
  • headers?: HeadersInit → opsional, untuk menambahkan atau menimpa header default.
  • signal?: AbortSignal → opsional, digunakan untuk membatalkan request kalau perlu (misal user pindah halaman sebelum request selesai).

Definisi fungsi apiFetch

export async function apiFetch<T>(endpoint: string, options: ApiOptions = {}): Promise<T> {
  const baseUrl = "http://127.0.0.1:8000/api";
  • <T> → generic type. Artinya kita bisa menentukan tipe data yang dikembalikan saat memanggil fungsi ini.
  • endpoint → path API relatif, misal /users atau /posts/1.
  • options → konfigurasi tambahan seperti headers, body, method. Defaultnya kosong {}.
  • baseUrl → URL dasar API. Kita hanya perlu menulis endpoint relatif ketika memanggil.

Blok try utama: memanggil API

const res = await fetch(`${baseUrl}${endpoint}`, {
  headers: {
    "Content-Type": "application/json",
    ...options.headers,
  },
  cache: "no-store",
  ...options,
});
  • fetch → fungsi built-in JavaScript untuk request HTTP.
  • headers → otomatis pakai Content-Type: application/json tapi bisa ditimpa dengan options.headers.
  • cache: "no-store" → memastikan data selalu fresh, tidak ambil dari cache browser.
  • ...options → spread operator untuk menambahkan properti lain yang mungkin dikirim user, seperti method: 'POST' atau body.

Parsing response JSON

let data: any;
try {
  data = await res.json();
} catch {
  data = null;
}
  • Kita mencoba membaca response dari server sebagai JSON.
  • Kalau server tidak mengembalikan JSON (misal plain text atau 204 No Content), kita set data = null.
  • Dengan ini, fungsi tidak langsung error saat memanggil res.json().

Mengecek status response

if (!res.ok) {
  const errorMsg = data?.message || `${res.status} ${res.statusText}` || "API Error";
  throw new Error(errorMsg);
}
  • res.ok → boolean, true kalau status HTTP 200–299.
  • Kalau response gagal:
    • Cek dulu apakah data punya properti message.
    • Kalau tidak, pakai status HTTP (404 Not Found atau 500 Internal Server Error).
    • Kalau semuanya gagal, beri default "API Error".
  • Lempar error agar bisa ditangkap di komponen pemanggil.

Mengembalikan data

return data as T;
  • Mengembalikan hasil JSON ke pemanggil, dengan type safety (as T).
  • Artinya, kalau kita memanggil apiFetch<User[]>("/users"), TypeScript tahu datanya array of User.

Catch block utama

} catch (err: any) {
  console.error("API Fetch Error:", err);
  throw new Error(err.message || "Unknown API error");
}
  • Menangkap error dari:
    • fetch gagal (misal network error)
    • res.ok tidak true
    • JSON parsing error
  • Log error ke console untuk debugging.
  • Lempar lagi error agar pemanggil bisa menanganinya dengan try-catch.

Materi Selanjutnya

Setelah inim kita akan belajar membuat services untuk resource “Product” yang memanfaatkan apiFetch yang sudah kita buat sebelumnya.

🔥 Flash Sale


📜 Table Of Contents


📌 Daftar Episode


Daftar eBook