Zustand: State Management Simpel dan Kuat untuk Aplikasi React Modern
1. Pendahuluan
Sebagai developer React, kita tahu bahwa mengelola state adalah salah satu tantangan terbesar dalam membangun aplikasi yang kompleks. Dari data pengguna, status loading, hingga tema aplikasi, semua perlu dikelola secara efisien agar aplikasi tetap responsif, mudah di-debug, dan scalable. Dulu, Redux menjadi solusi go-to bagi banyak orang, namun seringkali diikuti dengan boilerplate yang cukup banyak dan kurva pembelajaran yang curam.
Seiring berjalannya waktu, ekosistem React terus berevolusi, melahirkan berbagai solusi state management baru yang lebih ringan, lebih modern, dan lebih sesuai dengan paradigma hooks-based. Salah satu bintang yang bersinar terang adalah Zustand.
Zustand (yang berarti “state” dalam bahasa Jerman) adalah library state management yang minimalis namun sangat kuat, dibuat oleh tim di belakang Jotai dan React Spring. Filosofi utamanya adalah kesederhanaan dan performa. Jika Anda mencari alternatif Redux yang lebih ringkas atau ingin beralih dari Context API untuk global state yang lebih kompleks, Zustand bisa menjadi pilihan yang sangat menarik.
Artikel ini akan membawa Anda menyelami Zustand, mulai dari konsep dasarnya, cara instalasi, hingga implementasi praktis dengan contoh konkret. Mari kita permudah manajemen state Anda!
2. Mengapa Memilih Zustand? Kelebihan Utamanya
Sebelum kita masuk ke kode, mari kita pahami mengapa Zustand layak dipertimbangkan:
- Minimalis dan Ringan: Zustand memiliki ukuran bundle yang sangat kecil dan API yang sederhana. Anda bisa mulai menggunakannya hanya dengan beberapa baris kode.
- Tidak Ada Boilerplate: Lupakan reducers, actions, dispatchers, dan connect yang berlebihan. Zustand memungkinkan Anda membuat store dengan cara yang sangat intuitif, mirip dengan
useStatenamun untuk global state. - Hooks-Based: Sepenuhnya memanfaatkan React Hooks, sehingga integrasinya dengan komponen React terasa sangat alami.
- Performa Tinggi: Zustand dirancang untuk performa. Ia hanya akan me-render ulang komponen yang benar-benar membutuhkan data dari store, bukan seluruh komponen yang terhubung. Ini dicapai dengan mekanisme selector yang cerdas.
- Fleksibel: Store Zustand dapat digunakan di luar komponen React Anda, yang sangat berguna untuk logic di middleware atau event handler yang tidak terkait langsung dengan UI.
- TypeScript-Friendly: Mendukung TypeScript secara out-of-the-box dengan type inference yang sangat baik.
- Mudah Diuji: Karena store terpisah dari komponen, pengujian logic state menjadi lebih mudah dan terisolasi.
📌 Intinya: Jika Anda menginginkan state management yang kuat tanpa kerumitan, Zustand adalah jawabannya.
3. Instalasi dan Membuat Store Pertama Anda
Memulai dengan Zustand sangatlah mudah.
Pertama, instal library-nya:
npm install zustand
# atau
yarn add zustand
Sekarang, mari kita buat store sederhana untuk mengelola counter. Buat file src/store/counterStore.js (atau .ts jika Anda menggunakan TypeScript):
// src/store/counterStore.js
import { create } from 'zustand';
// Fungsi `create` menerima sebuah fungsi yang mengembalikan objek state dan fungsi-fungsi untuk memodifikasi state tersebut.
const useCounterStore = create((set) => ({
count: 0, // State awal
increment: () => set((state) => ({ count: state.count + 1 })), // Fungsi untuk menambah count
decrement: () => set((state) => ({ count: state.count - 1 })), // Fungsi untuk mengurangi count
reset: () => set({ count: 0 }), // Fungsi untuk mereset count
}));
export default useCounterStore;
✅ Penjelasan:
createadalah fungsi utama dari Zustand untuk membuat store.- Fungsi yang dilewatkan ke
createmenerimasetsebagai argumen.setadalah fungsi yang digunakan untuk memperbarui state. - Anda bisa mengembalikan objek yang berisi state awal (
count: 0) dan action (fungsi) yang memodifikasi state tersebut (increment,decrement,reset). - Fungsi
setbisa menerima objek parsial dari state yang ingin diubah, atau sebuah fungsi yang menerima state saat ini dan mengembalikan objek parsial yang baru. Pendekatan fungsi (set((state) => ...)) lebih disarankan karena memastikan Anda bekerja dengan state terbaru.
4. Menggunakan Store di Komponen React
Setelah store dibuat, menggunakannya di komponen React Anda semudah menggunakan useState.
// src/components/CounterDisplay.jsx
import React from 'react';
import useCounterStore from '../store/counterStore';
function CounterDisplay() {
// Hanya ambil state `count` dari store
const count = useCounterStore((state) => state.count);
return (
<div style={{ padding: '10px', border: '1px solid #ccc', borderRadius: '5px' }}>
<h3>Current Count: {count}</h3>
</div>
);
}
export default CounterDisplay;
// src/components/CounterControls.jsx
import React from 'react';
import useCounterStore from '../store/counterStore';
function CounterControls() {
// Hanya ambil fungsi action `increment` dan `decrement` dari store
const { increment, decrement, reset } = useCounterStore((state) => ({
increment: state.increment,
decrement: state.decrement,
reset: state.reset,
}));
return (
<div style={{ marginTop: '10px' }}>
<button onClick={increment} style={{ marginRight: '5px' }}>Increment</button>
<button onClick={decrement} style={{ marginRight: '5px' }}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
);
}
export default CounterControls;
Dan Anda bisa menggabungkannya di komponen utama Anda:
// src/App.js
import React from 'react';
import CounterDisplay from './components/CounterDisplay';
import CounterControls from './components/CounterControls';
function App() {
return (
<div style={{ fontFamily: 'sans-serif', padding: '20px' }}>
<h1>Zustand Counter App</h1>
<CounterDisplay />
<CounterControls />
</div>
);
}
export default App;
💡 Tips Penting: Selector dan Re-rendering
Perhatikan bagaimana kita mengambil state dari store: useCounterStore((state) => state.count);
Ini adalah selector Zustand. Ketika Anda hanya memilih sebagian dari state (misalnya, hanya count), komponen Anda hanya akan me-render ulang jika nilai count berubah. Jika ada bagian lain dari state yang berubah tapi count tidak, komponen CounterDisplay tidak akan me-render ulang. Ini adalah kunci performa Zustand!
Jika Anda mengambil seluruh state (useCounterStore((state) => state)), komponen akan me-render ulang setiap kali ada perubahan state di store, yang mungkin tidak optimal. Selalu usahakan untuk memilih hanya bagian state yang Anda butuhkan.
5. Mengelola State di Luar Komponen (Non-React)
Salah satu fitur unggulan Zustand adalah kemampuannya untuk berinteraksi dengan store di luar konteks komponen React. Ini sangat berguna untuk skenario seperti:
- Memperbarui state dari event handler DOM murni.
- Menginisialisasi state berdasarkan data dari
localStorageatau API saat aplikasi dimuat. - Mengakses state dari middleware atau utilitas lainnya.
Anda bisa mengakses state dan action secara langsung dari store yang Anda buat:
// src/utils/logStoreState.js
import useCounterStore from '../store/counterStore';
function logCurrentCounterState() {
// Mengakses state secara langsung (tanpa hook)
const currentState = useCounterStore.getState();
console.log('Current state (from outside React):', currentState.count);
// Memanggil action secara langsung
useCounterStore.setState({ count: currentState.count * 2 }); // Menggandakan nilai count
console.log('State after doubling (from outside React):', useCounterStore.getState().count);
}
export default logCurrentCounterState;
Anda bisa memanggil logCurrentCounterState() dari mana saja di aplikasi Anda (misalnya, di index.js atau setelah event tertentu).
// src/App.js (contoh penggunaan)
import React, { useEffect } from 'react';
import CounterDisplay from './components/CounterDisplay';
import CounterControls from './components/CounterControls';
import logCurrentCounterState from './utils/logStoreState'; // Import utilitas kita
function App() {
useEffect(() => {
// Panggil fungsi utilitas setelah komponen dimount
logCurrentCounterState();
}, []);
return (
<div style={{ fontFamily: 'sans-serif', padding: '20px' }}>
<h1>Zustand Counter App</h1>
<CounterDisplay />
<CounterControls />
</div>
);
}
export default App;
🎯 Use Case Real-world: Bayangkan Anda memiliki middleware untuk logging setiap kali state berubah, atau Anda ingin menyimpan state ke localStorage setiap kali ada perubahan. Kemampuan ini membuat Zustand sangat fleksibel.
6. Menggunakan Zustand dengan TypeScript
Zustand memiliki dukungan TypeScript yang sangat baik. Mari kita tingkatkan store counter kita dengan TypeScript untuk type safety yang lebih baik.
// src/store/counterStore.ts
import { create } from 'zustand';
// 1. Definisikan interface untuk state
interface CounterState {
count: number;
}
// 2. Definisikan interface untuk actions
interface CounterActions {
increment: () => void;
decrement: () => void;
reset: () => void;
}
// 3. Gabungkan kedua interface untuk tipe store lengkap
type CounterStore = CounterState & CounterActions;
const useCounterStore = create<CounterStore>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 }),
}));
export default useCounterStore;
Dengan TypeScript, Anda akan mendapatkan autocompletion yang lengkap dan type checking saat mengakses state atau memanggil action dari store Anda. Ini sangat membantu dalam menjaga konsistensi dan mencegah bug di aplikasi skala besar.
Kesimpulan
Zustand menawarkan pendekatan yang menyegarkan untuk state management di aplikasi React modern. Dengan API-nya yang minimalis, performa yang optimal melalui selector yang cerdas, dan fleksibilitas untuk digunakan di dalam maupun di luar komponen React, Zustand menjadi pilihan yang sangat menarik bagi developer yang mencari solusi yang lebih sederhana dan efisien dibandingkan Redux, namun lebih kuat dari Context API untuk global state yang kompleks.
Jika Anda merasa boilerplate Redux terlalu membebani atau Context API mulai terasa kurang memadai untuk kebutuhan Anda, saatnya mencoba Zustand. Anda mungkin akan terkejut betapa mudahnya mengelola state dengan library kecil namun perkasa ini!
🔗 Baca Juga
- Membangun Website Super Cepat dan Modern dengan Astro: Konsep Islands Architecture dan Integrasi Framework
- Membangun User Experience yang Responsif: Mengimplementasikan Optimistic UI
- Vite untuk Developer Modern: Mempercepat Pengembangan dan Build Aplikasi Frontend Anda
- Modern Frontend State Management: Memilih dan Mengelola State di Aplikasi Web Skala Besar