tutorial

84 Query & Mutation dari Frontend

84 Query & Mutation dari Frontend: Mengelola API dan Data Secara Efisien dari React

Dalam dunia pengembangan aplikasi modern, komunikasi antara frontend dan backend adalah arteri utama sebuah sistem. Kanal komunikasi itu biasanya terdiri dari dua jenis utama: query untuk mengambil data dan mutation untuk mengubah data. Pada artikel ini, saya ingin berbagi pengalaman, praktik terbaik, hingga simulasi kode nyata—tentang bagaimana mengelola 84 query dan mutation dari frontend, terutama React, secara efisien dan skalabel.

Catatan: Angka 84 di sini hanya ilustrasi. Namun, pada proyek nyata, tidak jarang kita punya puluhan, bahkan ratusan endpoint API untuk di-handle.

Mari kita mulai dengan tantangan dan peluang di balik skala ini.


Tantangan Mengelola Puluhan Query & Mutation di Frontend

Dengan bertambahnya jumlah fitur pada aplikasi, seringkali jumlah endpoint API ikut melonjak—query untuk membaca resource (list, detail, search), mutation untuk update, delete, create, dsb. Skala seperti 84 endpoint berarti:

  • Ada banyak HTTP request dari frontend ke backend.
  • Butuh manajemen data response yang konsisten di frontend.
  • Error handling menjadi kompleks.
  • State management harus efisien, agar user experience tetap mulus.

Bagaimana strategi seorang engineer agar tidak tenggelam dalam lautan request ini?


Arsitektur Manajemen Query/Mutation Modern

1. Layer Abstraksi API Service

Best practice saat ini adalah menyusun API service layer terpisah di frontend. Tujuannya: mengisolasi logic request-response dari logic tampilan.

// src/api/userApi.js
import axios from 'axios';

export const getUserList = () => axios.get('/api/users');
export const getUserDetail = (id) => axios.get(`/api/users/${id}`);
export const updateUser = (id, data) => axios.put(`/api/users/${id}`, data);
export const deleteUser = (id) => axios.delete(`/api/users/${id}`);
export const createUser = (data) => axios.post('/api/users', data);
// ... repeat for other resources up to 84 endpoint

2. Menggunakan Library Data-Fetching

Pustaka seperti React Query (TanStack Query) sangat membantu dalam hal:

  • Cache data secara otomatis.
  • Refetch dan invalidation otomatis saat ada perubahan data.
  • Loader dan error state out-of-the-box.

Dengan React Query, kita cukup mendefinisikan useQuery dan useMutation per endpoint.

// src/hooks/useUsers.js
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import * as userApi from "../api/userApi";

export const useUsers = () =>
  useQuery(['users'], userApi.getUserList);

export const useUser = (id) =>
  useQuery(['users', id], () => userApi.getUserDetail(id), {
    enabled: !!id,
  });

export const useUpdateUser = () => {
  const queryClient = useQueryClient();
  return useMutation(userApi.updateUser, {
    onSuccess: () => {
      queryClient.invalidateQueries(['users']);
    }
  });
};

Skema ini bisa diulang dengan pola serupa untuk resource lain, hingga 84 endpoint.


Simulasi: Daftar dan Update User

Mari kita simulasikan skenario dua query dan satu mutation yang sering dipakai: melihat daftar user, melihat detail, dan update user.

1. Menampilkan Daftar User

import { useUsers } from "./hooks/useUsers";

function UserList() {
  const { data, isLoading, error } = useUsers();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error loading users</div>;

  return (
    <ul>
      {data?.data.map(u => (
        <li key={u.id}>{u.name}</li>
      ))}
    </ul>
  );
}

2. Form Update User

import { useUpdateUser } from "./hooks/useUsers";

function UpdateUserForm({ user }) {
  const mutation = useUpdateUser();

  const onSubmit = (e) => {
    e.preventDefault();
    mutation.mutate({ id: user.id, data: { name: "Updated name"} });
  };

  return (
    <form onSubmit={onSubmit}>
      <input defaultValue={user.name} />
      <button disabled={mutation.isLoading}>Update</button>
      {mutation.isSuccess && <span>Success!</span>}
    </form>
  );
}

3. Tabel Manajemen Endpoint

ResourceQuery (READ)Mutation (CREATE)Mutation (UPDATE)Mutation (DELETE)
UsersgetUserListcreateUserupdateUserdeleteUser
ProductsgetProductListcreateProductupdateProductdeleteProduct
OrdersgetOrderListcreateOrderupdateOrderdeleteOrder
…84 API

Diagram Alur: Data Flow dari Komponen ke Server

Dengan menggunakan library seperti React Query, alur request-response secara global digambarkan sebagai berikut:

flowchart TD
    A[Komponen UI] -->|Trigger| B[useQuery/useMutation Hook]
    B -->|Call function| C[API Service Layer]
    C -->|HTTP Request| D[Backend REST/GraphQL API]
    D -->|Response| C
    C -->|Return data| B
    B -->|Update| E[State/Cache]
    E -->|Trigger re-render| A

Flow ini konsisten, tidak peduli apakah frontend kita punya 5, 50, atau 84 endpoint.


Menerapkan DRY (Don’t Repeat Yourself): Otomatisasi

Salah satu jebakan pada jumlah API banyak adalah boilerplate code. Untuk kasus 84 endpoint, copy-paste jadi masalah besar. Solusinya?

Abstraksi Hook Dinamis

Kita dapat membuat factory function untuk menghasilkan useQuery dan useMutation secara dinamis.

// src/hooks/useApiResource.js
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";

export function createResourceHooks(resource, apiFn) {
  return {
    useList: () =>
      useQuery([resource], apiFn.getList),
    useDetail: (id) =>
      useQuery([resource, id], () => apiFn.getDetail(id), { enabled: !!id }),
    useCreate: () => {
      const queryClient = useQueryClient();
      return useMutation(apiFn.create, {
        onSuccess: () => queryClient.invalidateQueries([resource]),
      });
    },
    // dst...
  };
}

Lalu, tinggal panggil:

import * as userApi from "../api/userApi";
const userHooks = createResourceHooks('users', userApi);
const { useList: useUsers, useCreate: useCreateUser } = userHooks;

Bayangkan penghematan waktu jika kita punya 84 resource!


Error Handling: Kunci Robust System

Frontend harus siap menghadapi error baik dari sisi jaringan, validasi, atau backend. Kuncinya adalah centralized error handling.

function ErrorBoundary({ error }) {
  return <div className="error">{error.message}</div>;
}

Gunakan di sekitar komponen penting atau jadikan interceptor global pada axios/fetch.


Kesimpulan dan Rekomendasi

Mengelola puluhan hingga ratusan query & mutation dari frontend bisa jadi tantangan besar, namun bukan mustahil!

Tips utama:

  1. Pisahkan API Service Layer agar mudah dirawat.
  2. Gunakan data fetching library seperti React Query untuk data sync, cache, error, dan loader state otomatis.
  3. Otomatisasi hook & request dengan abstraction DRY.
  4. Tabel/mapping resource supaya endpoint termonitor.
  5. Implementasikan error handling secara global.

Dengan pendekatan di atas, project dengan “84 Query & Mutation” pun akan tetap manageable, robust, dan mudah dikembangkan!

Referensi


Happy coding!
Jangan takut skalabilitas—struktur yang baik di awal akan menghemat waktu Anda, bahkan untuk 84 query & mutation di masa depan.

comments powered by Disqus