Reactjs Usesyncexternalstore Subscribe Getsnapshot External Store
Definisi
useSyncExternalStore adalah hook bawaan untuk membaca state dari store eksternal (bukan React state) sambil tetap aman terhadap concurrent rendering dan tearing. Ia mengambil subscribe (daftarkan listener) dan getSnapshot (baca nilai saat ini), serta opsional getServerSnapshot untuk SSR.
Kapan dipakai
Pakai saat state disimpan di luar React: store Redux/Zustand tingkat rendah, WebSocket, localStorage, media query, browser API. Jangan pakai untuk state lokal biasa (useState/useReducer cukup).
Cara kerja
Store minimal
let state = { count: 0 };
const listeners = new Set();
function emit() { listeners.forEach((l) => l()); }
export const store = {
subscribe(listener) {
listeners.add(listener);
return () => listeners.delete(listener);
},
getSnapshot() { return state; },
inc() { state = { count: state.count + 1 }; emit(); },
};Baca di komponen
import { useSyncExternalStore } from 'react';
function Counter() {
const snap = useSyncExternalStore(store.subscribe, store.getSnapshot);
return <button onClick={store.inc}>{snap.count}</button>;
}SSR aman
useSyncExternalStore(store.subscribe, store.getSnapshot, () => ({ count: 0 }));Struktur alur
Loading diagram...
Contoh dengan selector
function useStore(selector) {
return useSyncExternalStore(
store.subscribe,
() => selector(store.getSnapshot())
);
}Catatan implementasi
getSnapshotharus mengembalikan nilai referensi stabil bila tidak berubah; kalau tiap panggil bikin object baru, React akan loop render tak terbatas.- Untuk selector yang return object baru, cache hasil di store atau bandingkan via
useSyncExternalStoreWithSelector. getServerSnapshotwajib saat komponen di-render di server; kembalikan nilai deterministik.- Subscribe harus return unsubscribe function (cleanup).
Kesalahan umum
- Snapshot object baru tiap panggil: infinite re-render ("getSnapshot should be cached").
- Lupa return unsubscribe: listener menumpuk tiap mount.
- Mutasi state tanpa emit: React tidak tahu harus re-render.
- getServerSnapshot beda shape: hydration mismatch.