Belum reinvent-the-wheel, belum sah jadi js dev.
Siapa sih yang gak kenal Zustand, salah satu state management untuk React. Diantara zustand, mungkin banyak juga yang lebih prefer menggunakan alternatif lain seperti Redux
, Jotai
, Recoil
, dsb. Alasan saya pribadi menggunakan Zustand sebagai state management utamanya karena simple, ringan, dan boilerplate-free.
Setelah sekian lama menggunakan zustand maupun state managament lainnya, saya penasaran dong, gimana sih ini library cara kerjanya? Apa aja yg ada di belakangnya? Kok bisa ngelempar state yang sama ke beberapa component tanpa harus react context?
Yaudah daripada gabut pas ada waktu luang, jadinya saya nyoba nih buat zustand saya sendiri dari nol. Yuk langsung aja kita praktik.
React Context
Sebelumnya saya pernah make Context
& useState
bawaan react untuk manage state di app saya biar bisa dipake gak hanya di parent component, tetapi di children2 sampe di cucu & cicitnya juga bisa pake.
Awalnya oke aja tuh, tapi setelah appnya lumayan gede, muncul nih satu problem. Performanya jelek. Bisa dilihat di contoh atas, ketika tombol +
ataupun -
dipencet, sub-komponennya juga pada rerender juga semua (cek console & tgl/waktu yg dibawah).
Alasannya? semua sub-komponen terjadi rerender karena useState
nya berapa di parent component. Untuk project kecil seperti di atas mungkin tidak terlalu terasa, lain halnya misal sudah gede codebasenya.
Jadi, gimana nih solvenya biar cegah children component yang tidak menggunakan state tersebut tidak ikut rerender juga?
Pake state management semacam Zustand, jotai, atau lainnya yang bisa subscribe/listen state change per component.
Observable Pattern
Ketika ngulik2 design pattern untuk react, gak sengaja ada nemu yg namanya Observable Pattern. Pattern ini juga jadi dasar dari RxJs.
Berikut contoh simple dari implementasi Observable
.
Kayaknya cocok ya untuk ngerancang zustand from scratch?
Store
Pertama-tama, kita perlu membuat Store Creator
. Store ini nantinya akan menyimpan data, subscribe terhadap perubahan, dan mengubah data tersebut.
Fungsi ini yang akan bertanggung jawab untuk membuat penampungan state beserta observablenya, kemudian mengembalikan hasil berupa fungsi untuk mengambil data, mengubah data, dan berlangganan terhadap perubahan data.
State Observer Hooks
Store yang sudah kita buat sebelumnya sudah bisa menyimpan & mengubah data, tetapi belum bisa digunakan sebagai state di react. Agar bisa digunakan di komponen react, kita perlu “membungkus” store tersebut dengan custom hooks.
useStore.ts
import { useEffect, useState } from "react";
import { Store } from "./createStore";
const useStore = <T>(store: Store<T>) => {
// Buat state lokal untuk trigger rerender
// ketika ada perubahan state
const [state, setState] = useState<T>(store.getState());
useEffect(() => {
// Langganan terhadap perubahan state, dan ubah ketika
// terdapat perbedaan dengan state sebelumnya
const unsubscribe = store.subscribe((prev, next) => {
if (prev !== next) {
setState(next);
}
});
// Hentikan berlangganan ketika cleanup
return () => {
unsubscribe();
};
}, []);
return state;
};
export default useStore;
Penggunaan
Untuk menggunakan hooks di atas, kurang lebih sama seperti useStore
yang ada di zustand.
// Buat counter store
const counter = createStore(() => 0);
// Actions (ya, saya penganut no store actions)
// https://docs.pmnd.rs/zustand/guides/practice-with-no-store-actions
const increase = () => counter.setState((count) => count + 1);
const decrease = () => counter.setState((count) => count - 1);
const App = () => {
const count = useStore(counter);
return (
<div>
<p>Count: {count}</p>
<button onClick={decrease}>-</button>
<button onClick={increase}>+</button>
</div>
);
};
Setelah itu, mari kita coba gunakan “DIY Juztand” yang telah kita buat pada project React Context di atas dan mencoba memperbaiki issue rerender yang ada.
Jika kita lihat Console
dan menekan tombol -
ataupun +
, komponent yang rerender hanya komponen Counter
saja. Waktu/tgl yang ada di bawah juga sudah tidak mengalami perubahan.
Penutup
Dengan menggunakan state management & practice yang tepat, kita bisa meningkatkan performa react app kita agar lebih baik lagi. “DIY Juztand” yang telah dibuat di atas sangatlah simple, bahkan belum ada fitur selector
yang ada di library aslinya. Banyak hal yang masih bisa diimpove untuk DIY state management kita ini.
Semua ini untuk pembelajaran saja. Daripada menghabiskan waktu membuat dari nol, lebih baik menggunakan apa yang sudah ada saja, lebih cepat.
Source code dari hasil project di atas bisa dilihat disini.