Kembali ke Blog

Berhenti Mempersulit State: Kenapa Kebanyakan Aplikasi Web Tidak Butuh Redux

Refleksi arsitektur tentang bagaimana URL state dan native fetch cache sering kali mengalahkan global store yang berbelit-belit.

Salah satu kesalahan paling umum saat membangun aplikasi React adalah menganggap semua data harus masuk ke dalam global state.

Ketika sebuah form butuh filter kategori, reflek pertama banyak developer adalah membuat slice Redux, action creator, selector, dan dispatch event. Dua minggu kemudian, aplikasi memiliki puluhan reducer yang saling bergantung dan sulit didebug ketika terjadi race condition.

Padahal, sebagian besar data di antarmuka web bukanlah global state.

Membedah Tiga Kategori State Sebenarnya

Jika kita bedah secara objektif, data di frontend biasanya hanya terbagi menjadi tiga jenis:

  1. Server Cache (data dari database: daftar produk, profil pengguna, daftar invoice)
  2. URL State (parameter halaman: filter, pagination, tab aktif, query pencarian)
  3. Local UI State (apakah dropdown sedang terbuka, modal konfirmasi, input form sementara)

Ketika kita memisahkan ketiga hal ini dengan benar, kebutuhan akan global store seperti Redux atau Zustand sering kali turun drastis, bahkan mendekati nol.

1. Jadikan URL sebagai Sumber Kebenaran

Jika perubahan state memengaruhi apa yang dilihat pengguna dan seharusnya bisa dibagikan lewat tautan (seperti tab aktif atau nomor halaman), letakkan di URL query parameter (?page=2&tab=billing).

Keuntungan pendekatan ini:

  • Pengguna bisa me-refresh halaman tanpa kehilangan konteks.
  • Tautan bisa di-bookmark atau dikirim ke rekan kerja.
  • Tombol Back dan Forward di browser bekerja secara alami tanpa logika history manual.
// Membaca dari router bawaan Next.js
const router = useRouter();
const currentTab = router.query.tab || "overview";

function setTab(tab) {
  router.push({ query: { ...router.query, tab } }, undefined, { shallow: true });
}

2. Server Cache Bukan State Frontend

Data yang berasal dari database pada dasarnya adalah cache, bukan state murni milik browser. Data tersebut bisa kedaluwarsa sewaktu-waktu jika ada pengguna lain yang mengubahnya di server.

Mengelola siklus hidup cache (revalidation, refetching, background polling) di dalam store global kustom adalah cara tercepat menulis kode penuh bug. Serahkan pekerjaan ini ke mekanisme bawaan framework atau fetcher sederhana yang menangani cache invalidation secara otomatis.

3. Local State Tetap Lokal

Jika modal hanya terbuka di satu halaman, biarkan ia berada di komponen halaman tersebut dengan useState. Tidak perlu memindahkan status modal ke global store hanya karena "siapa tahu nanti dipakai di tempat lain".

Kaidah praktisnya: naikkan level state (lift state up) hanya saat komponen saudara kandung memang benar-benar membutuhkannya saat ini, bukan nanti.

Kapan Global State Benar-benar Dibutuhkan?

Global state tetap valid untuk skenario tertentu:

  • Keranjang belanja e-commerce multi-langkah yang belum tersimpan ke sesi database
  • Sistem audio player mini yang harus terus memutar musik saat pengguna berpindah halaman
  • Editor grafis atau kanvas interaktif dengan fitur undo/redo kompleks

Jika aplikasi Anda adalah SaaS dashboard, portal admin, atau platform marketplace reguler, arsitektur berbasis URL dan server cache akan membuat kode jauh lebih ringkas, mudah dipahami tim baru, dan minim bug.

Sederhana bukan berarti kurang fitur. Sederhana berarti tidak ada beban berlebih yang harus dirawat.