Belajar Zustand - Server State & Integrasi Data
Episode 12 of 23

Belajar Zustand - Server State & Integrasi Data

Episode ini membedakan server state dan client state, lalu menyusun aturan kapan data API masuk ke Zustand dan kapan ke TanStack Query atau SWR. Kalian juga belajar pola hybrid yang memisahkan cache server dari store global dengan contoh auth dan user profile.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Sebuah aplikasi modern tidak hanya menyimpan state UI di memori, tetapi juga berkomunikasi dengan API untuk mengambil data pengguna, daftar produk, dan lainnya. Pertanyaan yang sering muncul: data dari server itu masuk ke Zustand atau ke library cache seperti TanStack Query? Episode 12 menjawab pertanyaan itu dengan membedakan dua kategori state yang berbeda dan menyusun pola hybrid yang dipakai tim production.

Kalian akan memahami perbedaan server state dan client state, kriteria kapan data API masuk ke Zustand, kapan memakai TanStack Query atau SWR, lalu menyusun contoh auth dan user profile dengan pola hybrid.

Server State vs Client State

Server state adalah data yang dimiliki server dan disinkronkan lewat API: profil pengguna, daftar post, saldo akun. Client state adalah data yang lahir dan hidup di browser: status modal, nilai form, tema aktif, atau current page.

Perbedaan ini penting karena menentukan di mana data hidup. Server state butuh cache, retry, dan invalidasi ketika data berubah di server. Client state butuh kecepatan dan tidak perlu sinkron dengan server. Mencampur keduanya dalam satu store menyebabkan kode susah diprediksi: store ikut menangani loading, error, caching, dan refetch sekaligus.

Kapan Data API Masuk ke Zustand

Ada beberapa situasi di mana menyimpan data API di Zustand masuk akal:

  • Data dibaca di banyak komponen dan jarang berubah selama sesi.
  • Data dipakai untuk aksi global seperti autentikasi.
  • Data perlu diubah secara lokal sebelum dikirim kembali ke server.

Contoh paling umum adalah token dan profil sesi pengguna. Token harus tersedia secara sinkron untuk setiap request, dan sebaiknya tidak berubah-ubah:

JSAuth session di Zustand
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
 
interface AuthState {
  token: string | null
  user: User | null
  setSession: (token: string, user: User) => void
  clearSession: () => void
}
 
export const useAuth = create<AuthState>()(
  persist(
    (set) => ({
      token: null,
      user: null,
      setSession: (token, user) => set({ token, user }),
      clearSession: () => set({ token: null, user: null }),
    }),
    { name: 'auth-session' },
  ),
)

setSession(token, user) menyimpan data sesi sekali per login, dan komponen mana pun bisa membaca token secara sinkron tanpa menunggu response ulang dari API.

Kapan Memakai TanStack Query atau SWR

Ketika data sering berubah di server dan dibaca ulang berkali-kali, gunakan library server cache. TanStack Query dan SWR menyediakan caching, deduplication request, retry, refetch on window focus, dan invalidasi query — fitur yang tidak ada di Zustand.

Instal TanStack Query di project kalian:

Install TanStack Query
npm i @tanstack/react-query

Lalu definisikan query dengan queryKey dan queryFn:

JSQuery profil pengguna
import { useQuery } from '@tanstack/react-query'
 
export function useUserProfile(userId: string) {
  return useQuery({
    queryKey: ['user', userId],
    queryFn: () =>
      fetch(`/api/users/${userId}`).then((res) => res.json()),
    staleTime: 60_000,
  })
}

queryKey: ['user', userId] membuat cache per pengguna, dan staleTime 60 detik mencegah refetch yang berlebihan.

Pola Hybrid: Zustand dan TanStack Query

Kombinasi paling sehat: Zustand menyimpan state client global seperti token dan preferensi, TanStack Query menyimpan cache server. Ketika user berubah, invalidasi query di TanStack Query dan update token di Zustand:

JSInvalidasi query setelah login
async function login(email: string, password: string) {
  const res = await fetch('/api/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password }),
  })
  const data = await res.json()
  useAuth.getState().setSession(data.token, data.user)
  await queryClient.invalidateQueries({ queryKey: ['user'] })
}

useAuth.getState().setSession(...) mengupdate store global, sementara invalidateQueries memaksa TanStack Query mengambil ulang profil terkait. Dengan pola ini, store tidak pernah menyimpan cache server, dan server cache tidak pernah menangani aksi global.

Penutup

Episode 12 memisahkan dua dunia state: server state yang hidup di TanStack Query atau SWR, dan client state yang hidup di Zustand. Data sesi dan UI masuk ke Zustand; data yang berubah di server dan dibaca berkali-kali masuk ke cache query dengan invalidasi.

Inti yang harus dibawa pulang:

  • Server state butuh cache, retry, dan invalidasi; client state butuh kecepatan.
  • Token dan sesi auth cocok disimpan di Zustand agar tersedia secara sinkron.
  • TanStack Query dan SWR menangani caching data API dengan queryKey dan staleTime.
  • Pola hybrid memisahkan cache server dari store global.
  • useAuth.getState().setSession mengupdate store dari luar hook.
  • invalidateQueries menyinkronkan cache query setelah aksi login atau logout.

Di episode 13 selanjutnya kita akan membahas performance dan transient updates — mengontrol re-render dengan selector dan useShallow, menghindari object baru setiap render, serta memperbarui state seperti progress bar tanpa memicu render.

Belajar Zustand - Server State & Integrasi Data | Belajar Zustand