📒 Ridwan Aji Bari - Blog

Mengelola State Kompleks di React dengan Zustand

30 Juni 2026•5 menit baca

Pendahuluan

Pada artikel sebelumnya, kita telah membahas bagaimana React State dasar bekerja menggunakan hook useState. Untuk komponen sederhana, useState adalah solusi yang sangat baik. Namun seiring berkembangnya aplikasi, Anda akan mulai menghadapi tantangan baru dalam mengelola data.

Ketika banyak komponen yang berjauhan perlu mengakses atau mengubah data yang sama, menggunakan useState saja akan memaksa Anda melakukan prop drilling (mengirim props melewati banyak level komponen perantara) atau menggunakan React Context. Sayangnya, React Context memiliki kelemahan inheren: setiap kali nilai Context berubah, semua komponen yang mengonsumsi Context tersebut akan dirender ulang, meskipun mereka hanya menggunakan sebagian kecil dari data tersebut.

Di sinilah kita membutuhkan solusi State Management eksternal yang lebih canggih, dan salah satu pustaka terpopuler saat ini adalah Zustand.


Apa itu Zustand?

Zustand (artinya keadaan dalam bahasa Jerman) adalah pustaka manajemen state untuk React yang sangat ringan (ukurannya kurang dari 10KB), cepat, dan sangat mudah digunakan.

Berbeda dengan Redux yang terkenal dengan boilerplate yang rumit (action, reducer, dispatch, dll.), atau React Context yang membutuhkan pembungkusan komponen induk dengan <Provider>, Zustand bekerja dengan konsep yang jauh lebih sederhana berbasis custom hooks.


Perbandingan: Dengan vs Tanpa Zustand

Mari kita bayangkan sebuah studi kasus sederhana: Aplikasi Toko Online. Kita memiliki dua komponen yang letaknya berjauhan secara hierarki:

  1. Navbar: Membutuhkan data jumlah barang di keranjang (totalItems).
  2. ProductList: Memiliki tombol untuk menambah barang ke keranjang (addToCart).

Pendekatan 1: Tanpa Zustand (Lifting State Up & Prop Drilling)

Jika hanya menggunakan React murni, kita terpaksa harus mengangkat (lift state up) state keranjang ke komponen induk terdekat yang menyelimuti keduanya (misalnya App), lalu menyalurkannya ke bawah lewat props.

// Komponen Induk (App.jsx)
function App() {
  const [cartItems, setCartItems] = useState([]);

  const addToCart = (product) => {
    setCartItems([...cartItems, product]);
  };

  return (
    <div>
      {/* Harus dipass ke Navbar */}
      <Navbar totalItems={cartItems.length} />
      {/* Harus dipass ke ProductList */}
      <ProductList addToCart={addToCart} />
    </div>
  );
}

Kelemahan Cara Ini:

  • Prop Drilling: Jika komponen Navbar atau ProductList berada jauh di dalam struktur folder (misal: App -> Header -> Navigation -> Navbar), kita harus mengalirkan prop tersebut melewati komponen-komponen perantara yang sebenarnya tidak membutuhkannya.
  • Kerapihan Kode: Komponen induk (App) menjadi sangat padat dengan berbagai logika modifikasi data yang bukan merupakan tanggung jawab utamanya.

Cara Menggunakan Zustand

Mari kita buat sebuah simulasi toko online sederhana di mana kita perlu menyimpan data keranjang belanja (shopping cart). Kita ingin status keranjang belanja ini dapat diakses oleh komponen Navbar (untuk menampilkan jumlah barang) dan komponen ProductList (untuk menambah barang).

1. Instalasi Zustand

Pertama-tama, instal pustaka Zustand di proyek Anda:

npm install zustand

2. Membuat Store

Buat sebuah file baru bernama cartStore.js (atau .ts jika menggunakan TypeScript). Di file ini, kita akan mendefinisikan store global kita menggunakan fungsi create dari Zustand:

import { create } from 'zustand';

// Mendefinisikan store global
const useCartStore = create((set) => ({
  // 1. Nilai State Awal
  cartItems: [],
  totalItems: 0,

  // 2. Actions (Fungsi untuk mengubah state)
  addToCart: (product) => 
    set((state) => {
      const updatedCart = [...state.cartItems, product];
      return {
        cartItems: updatedCart,
        totalItems: updatedCart.length,
      };
    }),

  clearCart: () => set({ cartItems: [], totalItems: 0 }),
}));

export default useCartStore;

Penjelasan Kode:

  • create: Berfungsi untuk membungkus deklarasi state dan actions kita menjadi sebuah hook React.
  • set: Parameter fungsi yang digunakan untuk memperbarui state secara aman. Zustand menggunakan prinsip penggabungan (shallow merge), sehingga Anda hanya perlu mengembalikan properti yang ingin diubah.

3. Menggunakan Store pada Komponen

Sekarang, kita bisa langsung menggunakan hook useCartStore di komponen mana pun tanpa perlu dibungkus oleh Provider apa pun!

Komponen Navbar (Membaca State)

import useCartStore from './cartStore';

function Navbar() {
  // Mengambil hanya properti 'totalItems' secara spesifik (selector)
  const totalItems = useCartStore((state) => state.totalItems);

  return (
    <nav class="flex justify-between p-4 bg-gray-100">
      <span class="font-bold">Aji Store</span>
      <div class="relative">
        🛒 Keranjang
        <span class="ml-1 bg-red-500 text-white rounded-full px-2 py-0.5 text-xs">
          {totalItems}
        </span>
      </div>
    </nav>
  );
}

Komponen Product (Menjalankan Action)

import useCartStore from './cartStore';

const PRODUCTS = [
  { id: 1, name: 'Kopi Susu Gula Aren', price: 18000 },
  { id: 2, name: 'Croissant Cokelat', price: 22000 },
];

function ProductList() {
  // Mengambil action 'addToCart'
  const addToCart = useCartStore((state) => state.addToCart);

  return (
    <div class="p-4 grid gap-4">
      {PRODUCTS.map((product) => (
        <div key={product.id} class="border p-4 rounded-lg flex justify-between">
          <div>
            <h3 class="font-semibold">{product.name}</h3>
            <p class="text-sm text-gray-500">Rp {product.price}</p>
          </div>
          <button 
            onClick={() => addToCart(product)}
            class="bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700"
          >
            Tambah +
          </button>
        </div>
      ))}
    </div>
  );
}

Mengapa Zustand Lebih Unggul Dibanding React Context?

Zustand menawarkan beberapa kelebihan yang membuatnya sangat diminati:

  1. Optimasi Performa Otomatis (Select Selector): Perhatikan kode ini: const totalItems = useCartStore((state) => state.totalItems). Dengan menuliskan selector (state) => state.totalItems, komponen Navbar hanya akan dirender ulang jika nilai totalItems berubah. Jika properti lain di dalam store berubah (misalnya data detail produk lain), Navbar tidak akan ikut merender ulang. Ini memecahkan masalah performa pada React Context secara tuntas.

  2. Tanpa Boilerplate: Tidak ada lagi file reducer yang panjang, tipe aksi (action types) yang rumit, atau pembungkus Provider di file main.jsx or App.jsx Anda. Cukup buat store, lalu impor hook-nya langsung di komponen yang dituju.

  3. Pengelolaan State di Luar Komponen: Karena Zustand adalah sistem state JavaScript murni, Anda bahkan dapat berinteraksi dengan store Anda dari luar komponen React (misalnya di dalam file utilitas pengiriman API biasa).


Kesimpulan

Untuk aplikasi kecil, useState bawaan React sudah sangat mumpuni. Namun, ketika aplikasi Anda bertumbuh menjadi lebih kompleks dengan kebutuhan berbagi state lintas komponen yang berjauhan, Zustand adalah pilihan cerdas, modern, dan sangat nyaman yang dapat menggantikan Redux maupun React Context dengan kode yang bersih dan performa maksimal.