Cara Fetch Api di Client Component Next Js untuk Data Interaktif

Cara fetch API di Client Component Next.js yang benar adalah memanggil fetch di dalam useEffect setelah komponen mount, lalu simpan hasilnya ke state data, loading, dan error. Langkah yang paling sering dilewatkan adalah cleanup dengan AbortController agar request batal saat komponen unmount atau user mengetik ulang.

Pola Fetch di Client Component yang Benar

Server Component mengambil data sekali saat render di server. Client Component mengambil data dari browser setelah halaman tampil.

Gunakan fetch client hanya untuk data interaktif. Contohnya:

  • Pencarian dan filter yang berubah tanpa reload halaman.
  • Tombol refresh manual atau pagination di sisi client.
  • Data yang bergantung pada input user, tab aktif, atau interval polling.

Langkah Fetch API dengan useEffect

Ikuti urutan ini agar loading dan error tidak bocor ke UI.

  1. Tambahkan use client di baris pertama, lalu buat state data, loading, dan error.
  2. Panggil fetch di dalam useEffect dengan AbortController untuk membatalkan request lama.
  3. Render tiga kondisi secara eksplisit: loading, error, dan data kosong.
'use client';
import { useEffect, useState } from 'react';

export default function ProductList() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const controller = new AbortController();
    async function load() {
      try {
        const res = await fetch('/api/products', {
          signal: controller.signal,
        });
        if (!res.ok) throw new Error('Gagal memuat produk');
        setData(await res.json());
      } catch (err) {
        if (err.name !== 'AbortError') setError(err.message);
      } finally {
        setLoading(false);
      }
    }
    load();
    return () => controller.abort();
  }, []);

  if (loading) return <p>Memuat produk...</p>;
  if (error) return <p>Error: {error}</p>;
  if (data.length === 0) return <p>Belum ada produk.</p>;
  return (
    <ul>
      {data.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}

Perbandingan Sumber Data Client

Sumber Kapan Dipakai Catatan
Route Handler internal Data milik aplikasi sendiri Validasi input di server
API eksternal Layanan pihak ketiga Jangan kirim secret dari browser
Server Action Mutasi form dan data privat Cek status dan auth di server
  • Simpan token, API secret, dan kredensial database hanya di server. Kirim dari client cukup ID atau parameter pencarian.
  • Validasi tetap jalan di server walaupun client sudah validasi. Client mudah dimodifikasi user.
  • Periksa res.ok, status HTTP seperti 404 dan 500, serta bentuk JSON sebelum masuk ke state.

FAQ

Apakah boleh fetch langsung di body Client Component?

Tidak. Taruh di useEffect atau event handler agar tidak memicu request tiap render.

Bagaimana hindari double fetch saat dev?

Itu efek StrictMode. Pastikan cleanup mengembalikan controller.abort().

Kapan pindah ke Server Component?

Saat data cukup diambil sekali saat render awal dan tidak berubah oleh interaksi user.