React

Basic Consume API

Proses consume API adalah langkah-langkah yang dilakukan oleh aplikasi atau sistem untuk mengakses dan menggunakan data atau layanan yang disediakan oleh API.

Author : Celvine Adi Putra | Date : November, 18 2025

Tutorial Consume API

Prasyarat

Sebelum memulai, pastikan komputer Anda sudah siap dengan:

  • Node.js (Versi 22 atau lebih baru disarankan).
  • MongoDB (Pastikan MongoDB Service sudah berjalan di latar belakang).
  • Git (Untuk meng-clone repository).

Persiapan Backend: Menyiapkan Movie API untuk Praktek Consume Data

Jika kamu belum punya project backend nya atau error silahkan ikutin langkah ini atau jika sudah punya silahkan di skip

Langkah 1: Clone backend

Langkah pertama adalah mengambil kode proyek API yang sudah disiapkan. Kita akan menggunakan perintah git clone. Buka terminal atau command prompt kamu, lalu jalankan:

bash
git clone https://github.com/StayLearnCode/movie-express.git

Langkah 2: Instalasi Dependencies

Setelah berhasil di-clone, kita perlu masuk ke folder proyek tersebut dan menginstal paket-paket yang diperlukan agar kode bisa berjalan.

bash
cd movie-express
npm install

Langkah 3: Mengisi Data Awal (Database Seeding)

Kita perlu melakukan Seeding. Seeding adalah proses mengisi database dengan data awal/contoh secara otomatis.

Jalankan perintah berikut secara berurutan:

bash
cd seeders
node index.js

Langkah 4: Menjalankan Server

Sekarang datanya sudah ada, saatnya menyalakan server!

Pertama, kita harus keluar dulu dari folder seeders untuk kembali ke folder utama, lalu jalankan servernya.

bash
cd ..
npm run dev

Persiapan Frontend: Mengintegrasikan Axios pada React

Sebelum kita mulai menulis kode untuk mengambil data, pastikan kamu telah membuka kembali project React yang kita gunakan pada materi Basic React Router. Kita akan melanjutkan pengembangan.

Mengapa Kita Menggunakan Axios?

Untuk mengambil data dari API, JavaScript sebenarnya menyediakan fitur standar browser yang disebut Fetch API. Kita bisa menggunakannya tanpa perlu menginstal apa pun.

Namun, dalam pengembangan aplikasi skala produksi, Fetch API memiliki beberapa keterbatasan teknis yang membuatnya kurang efisien untuk digunakan secara langsung:

  • Penanganan JSON Manual: Anda harus melakukan parsing data JSON secara manual di setiap request.
  • Penanganan Error Terbatas: Fetch tidak menganggap status HTTP 404 atau 500 sebagai error secara default, sehingga memerlukan logika tambahan untuk menanganinya.
  • Kode Berulang (Boilerplate): Memerlukan lebih banyak baris kode untuk pengaturan header dan konfigurasi request.

Oleh karena itu, kita akan menggunakan Axios. Axios adalah library HTTP Client yang mengatasi masalah teknis di atas. Ia menangani parsing JSON secara otomatis, memiliki penanganan error yang lebih baik, dan membuat sintaks kode kita menjadi lebih ringkas dan mudah dibaca.

Langkah 1: Instalasi Library Axios

Karena Axios adalah library eksternal, kita perlu menambahkannya ke dalam project kita terlebih dahulu. Buka terminal kamu dan pastikan kamu berada di dalam folder project React, lalu jalankan perintah berikut:

bash
npm install axios

Langkah 2: Menjalankan Project

Setelah instalasi selesai, mari kita pastikan tidak ada error yang terjadi akibat penambahan library baru tersebut. Jalankan server pengembangan dengan perintah:

bash
npm run dev

Jika server berjalan tanpa pesan error di terminal, berarti Axios telah berhasil terinstal dan project kamu siap untuk tahap selanjutnya.

Langkah 3: Membuat utils atau helpers untuk Axios

Dalam pengembangan aplikasi yang skalabel, menulis URL API lengkap (misalnya http://localhost:3000/api/movies) secara berulang di setiap komponen adalah praktik yang tidak efisien. Jika alamat server berubah, Anda harus mengubahnya di banyak tempat.

Solusinya adalah membuat satu instance Axios yang dikonfigurasi secara terpusat. Kita akan menempatkan konfigurasi ini dalam folder utils (utilities) atau helpers.

Silakan buat folder baru bernama utils di dalam direktori src, kemudian buat file baru bernama ApiClient.ts.

ApiClient.ts

Selanjutnya, salin kode berikut ke dalam file ApiClient.ts:

ApiClient.ts
import axios from "axios"

const ApiClient = axios.create({
    baseURL : "http://localhost:3000/api",
    headers : {
        "Content-Type": "application/json",
    }
})

export default ApiClient;

Penjelasan Kode:

  • axios.create({...}): Fungsi ini membuat instance baru dari Axios. Instance ini adalah versi Axios yang telah kita sesuaikan pengaturan standarnya.
  • baseURL: Kita menetapkan alamat dasar API. Nantinya, saat memanggil endpoint (misalnya /movies), Axios akan otomatis menggabungkannya menjadi http://localhost:3000/api/movies. Ini membuat kode di komponen lain menjadi lebih bersih.
  • headers: Kita menetapkan standar header Content-Type: application/json untuk memastikan server tahu bahwa data yang kita kirim atau minta berformat JSON.
  • export default: Kita mengekspor konfigurasi ini agar bisa diimpor dan digunakan di seluruh bagian aplikasi.

Consume API

Sekarang setelah konfigurasi Axios (ApiClient) siap, kita akan masuk pada tahap menghubungkan halaman frontend dengan data dari backend.

Mengimplementasikan Fitur Read (Fetch Data)

Langkah-langkah Update Component Movies

Silakan buka file src/pages/Movies.tsx. Kita akan melakukan perubahan signifikan pada file ini untuk menangani tiga kondisi utama dalam pengambilan data:

  • Loading: Saat data sedang diambil.
  • Success: Saat data berhasil diambil.
  • Error: Saat terjadi kegagalan (misalnya server mati).

Copas kode berikut untuk menggantikan isi file Movies.tsx Kamu:

Movies.tsx
import { NavLink } from "react-router";
import { useCallback, useEffect, useState } from "react";
import ApiClient from "../utils/ApiClient"; // Pastikan path import sesuai dengan struktur folder Anda
import { Table } from "react-bootstrap";

// 1. Definisi Tipe Data
interface Movie {
    _id: string;
    judul: string;
    tahunRilis: string;
    sutradara: string;
    createdAt: string;
    updatedAt: string;
}

function Movies() {
    // 2. State Management
    const [movies, setMovies] = useState<Movie[]>([]);
    const [loading, setLoading] = useState<boolean>(true);
    const [error, setError] = useState<string | null>(null);

    // 3. Fungsi Pengambilan Data
    const fetchMovies = useCallback(async () => {
        setLoading(true); // Mulai status loading
        setError(null);   // Reset error sebelum mencoba request baru

        try {
            const response = await ApiClient.get("/movies");
            if (response.status === 200) {
                setMovies(response.data.data);
            }
        } catch (error) {
            console.error("Error fetching data:", error);
            setError("Gagal mengambil data dari server.");
        } finally {
            setLoading(false); // Hentikan status loading apapun hasilnya
        }
    }, []);

    // 4. Lifecycle Hook
    useEffect(() => {
        fetchMovies();
    }, [fetchMovies]);

    return (
        <div className="container mx-auto py-3">
            <div className="d-flex justify-content-between mb-3">
                <h4>Daftar Film</h4>
                <NavLink to="/add-movie" className="btn btn-primary">
                    Tambah Film
                </NavLink>
            </div>

            {/* 5. Conditional Rendering */}
            <div>
                <Table striped bordered hover size="sm">
                    <thead>
                        <tr>
                            <th>No</th>
                            <th>Judul</th>
                            <th>Tahun Rilis</th>
                            <th>Sutradara</th>
                        </tr>
                    </thead>
                    <tbody>
                        {/* Kondisi 1: Sedang Memuat */}
                        {loading && (
                            <tr>
                                <td colSpan={4} className="text-center">Sedang memuat data...</td>
                            </tr>
                        )}

                        {/* Kondisi 2: Terjadi Error */}
                        {error && (
                            <tr>
                                <td colSpan={4} className="text-center text-danger">{error}</td>
                            </tr>
                        )}

                        {/* Kondisi 3: Data Kosong */}
                        {!loading && !error && movies.length === 0 && (
                            <tr>
                                <td colSpan={4} className="text-center">Tidak ada data film tersedia.</td>
                            </tr>
                        )}

                        {/* Kondisi 4: Data Berhasil Dimuat */}
                        {!loading && !error && movies.length > 0 && movies.map((movie, index) => (
                            <tr key={movie._id}>
                                <td>{index + 1}</td>
                                <td>{movie.judul}</td>
                                <td>{movie.tahunRilis}</td>
                                <td>{movie.sutradara}</td>
                            </tr>
                        ))}
                    </tbody>
                </Table>
            </div>
        </div>
    );
}

export default Movies;

Penjelasan Kode

1. TypeScript Interface (interface Movie)

Kita mendefinisikan struktur data Movie. Ini membantu TypeScript memvalidasi bahwa data yang kita terima dari API dan data yang kita tampilkan di tabel memiliki struktur yang konsisten, sehingga mencegah error properti undefined.

2. State Management (useState)

Kita menggunakan tiga state terpisah untuk mengontrol UI:

  • movies: Array untuk menyimpan data film yang berhasil diambil.
  • loading: Boolean (true/false) untuk menentukan apakah indikator loading harus muncul. Defaultnya true agar loading muncul saat halaman pertama kali dibuka.
  • error: String untuk menyimpan pesan kesalahan jika request gagal.
3. fetchMovies dengan useCallback

Fungsi ini bertugas memanggil API.

  • ApiClient.get("/movies"): Kita hanya menulis /movies karena baseURL sudah diatur di ApiClient.ts.
  • try...catch...finally: Blok ini penting untuk menangani alur request. Jika sukses, data disimpan. Jika gagal, error dicatat. Blok finally memastikan status loading dimatikan, baik request itu sukses maupun gagal.
  • useCallback: Kita membungkus fungsi ini agar referensi memorinya tidak berubah setiap kali komponen di-render ulang, mencegah infinite loop pada useEffect.
4. useEffect Hook

Hook ini berfungsi sebagai pemicu. Dengan array dependency [fetchMovies], React akan menjalankan fungsi fetchMovies segera setelah komponen Movies di-mount (ditampilkan) ke layar.

5. Conditional Rendering

Di dalam bagian return (JSX), kita tidak sekadar menampilkan tabel. Kita menangani pengalaman pengguna (User Experience) dengan logika:

  • Jika loading true -> Tampilkan teks "Sedang memuat...".
  • Jika error ada -> Tampilkan pesan error merah.
  • Jika data kosong -> Beritahu user bahwa belum ada data.
  • Jika semua lancar -> Lakukan mapping data movies ke dalam baris tabel (<tr>).

Create New Movie

Update Movie

Delete Movie