Pertanyaan Interview Zustand 2026: State Management React dan Praktik Terbaik

Pertanyaan dan jawaban interview Zustand untuk tahun 2026. Pelajari pola state management, middleware, TypeScript, dan perbandingan Zustand dengan Redux dan Context.

Pertanyaan Interview Zustand 2026: State Management React dan Praktik Terbaik

Zustand telah menjadi library state management pilihan utama untuk aplikasi React yang membutuhkan lebih dari Context API namun tidak serumit Redux. Dengan API yang minimal dan desain TypeScript-first, pertanyaan tentang Zustand kini sering muncul dalam interview frontend, terutama untuk posisi React level menengah dan senior.

Apa yang Dicari Interviewer

Pertanyaan interview Zustand menguji tiga area: pemahaman tentang pola store versus state bawaan React, pengetahuan tentang kapan Zustand lebih unggul dari alternatif lain, dan kemampuan menyusun store untuk maintainability.

Konsep Dasar Zustand yang Harus Dikuasai Setiap Kandidat

Zustand v5, yang dirilis akhir 2024, memperkenalkan beberapa breaking changes dari v4. Fungsi create tidak lagi memerlukan panggilan useStore terpisah, dan middleware persist kini menggunakan model hydration sinkron secara default. Interviewer mengharapkan kandidat mengetahui API terkini.

Apa yang membuat Zustand berbeda dari useState dan useReducer?

Zustand store berada di luar component tree React. Perbedaan arsitektur ini memiliki tiga konsekuensi praktis:

  1. State bertahan meskipun component mount dan unmount tanpa memerlukan Context provider
  2. Update tidak memicu re-render parent, hanya component yang berlangganan yang re-render
  3. State dapat diakses secara sinkron di luar React, berguna untuk event handler dan logika async
store.tstypescript
import { create } from 'zustand'

interface CartStore {
  items: CartItem[]
  addItem: (item: CartItem) => void
  clearCart: () => void
  totalPrice: () => number
}

export const useCartStore = create<CartStore>((set, get) => ({
  items: [],
  addItem: (item) => set((state) => ({ 
    items: [...state.items, item] 
  })),
  clearCart: () => set({ items: [] }),
  totalPrice: () => get().items.reduce((sum, item) => sum + item.price, 0)
}))

Fungsi get menyediakan akses sinkron ke state saat ini, menghindari masalah stale closure yang umum terjadi dengan useState.

Bagaimana Zustand menangani re-render?

Zustand menggunakan shallow equality secara default. Ketika sebuah component berlangganan ke store dengan useCartStore(), component tersebut menerima seluruh objek state dan re-render pada setiap perubahan. Memilih slice tertentu mencegah render yang tidak perlu:

Component.tsxtypescript
// Buruk: re-render pada setiap perubahan store
const { items } = useCartStore()

// Baik: re-render hanya ketika items berubah
const items = useCartStore((state) => state.items)

// Multiple values: gunakan shallow comparison
import { shallow } from 'zustand/shallow'

const { items, totalPrice } = useCartStore(
  (state) => ({ items: state.items, totalPrice: state.totalPrice() }),
  shallow
)

Comparator shallow dari zustand/shallow melakukan reference equality pada properti objek, bukan objek itu sendiri.

Zustand vs Context API: Kapan Memilih Masing-masing

Pertanyaan perbandingan ini muncul di hampir setiap interview yang membahas state management. Jawabannya tergantung pada frekuensi update dan kompleksitas state.

KriteriaContext APIZustand
Bundle size0 KB (bawaan)1.2 KB gzipped
Kontrol re-renderManual dengan memo/useMemoSelector bawaan
DevToolsHanya React DevToolsKompatibel dengan Redux DevTools
Server componentsDukungan penuhMemerlukan client boundary
Async stateMemerlukan wrapperDukungan native

Context API bekerja dengan baik untuk nilai yang jarang berubah seperti tema atau locale. Zustand unggul ketika update state terjadi sering, seperti input form, data real-time, atau shopping cart. Dokumentasi React tentang state management merekomendasikan lifting state up dan menggunakan Context untuk masalah "prop drilling", sementara external store cocok untuk pola update yang kompleks.

Pertimbangan Server Components

Zustand store memerlukan directive "use client". Untuk aplikasi yang menggunakan React Server Components secara ekstensif, ini berarti state Zustand hanya ada di client component. Arsitektur hybrid sering meneruskan data yang di-fetch dari server sebagai props ke client component yang kemudian sync dengan Zustand.

Pola Middleware di Zustand

Pertanyaan middleware menguji apakah kandidat memahami komposisi di atas konfigurasi. Middleware Zustand membungkus fungsi store creator, menambahkan behavior tanpa mengubah core API.

Bagaimana middleware persist bekerja?

store.tstypescript
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'

interface UserPreferences {
  theme: 'light' | 'dark'
  language: string
  setTheme: (theme: 'light' | 'dark') => void
}

export const usePreferencesStore = create<UserPreferences>()(
  persist(
    (set) => ({
      theme: 'light',
      language: 'en',
      setTheme: (theme) => set({ theme })
    }),
    {
      name: 'user-preferences',
      storage: createJSONStorage(() => localStorage),
      partialize: (state) => ({ theme: state.theme, language: state.language })
    }
  )
)

Opsi partialize mengecualikan fungsi dan derived state dari persistence. Tanpa opsi ini, serialization gagal atau storage membengkak dengan data yang tidak perlu. Dokumentasi Zustand tentang persist membahas strategi migrasi untuk perubahan schema.

Menggabungkan beberapa middleware

Middleware di-compose dari dalam ke luar. Middleware paling dalam dieksekusi terlebih dahulu:

store.tstypescript
import { create } from 'zustand'
import { devtools, persist, subscribeWithSelector } from 'zustand/middleware'
import { immer } from 'zustand/middleware/immer'

export const useStore = create<StoreState>()(
  devtools(
    persist(
      subscribeWithSelector(
        immer((set) => ({
          // state dan actions
        }))
      ),
      { name: 'app-storage' }
    ),
    { name: 'AppStore' }
  )
)

Middleware immer memungkinkan update gaya mutable yang menghasilkan state immutable. Middleware subscribeWithSelector memungkinkan berlangganan ke slice state di luar component React.

Siap menguasai wawancara React / Next.js Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Pola Integrasi TypeScript

Zustand v5 meningkatkan type inference secara signifikan. Pola panggilan fungsi ganda create<Type>()() menyediakan type inference penuh untuk middleware chain.

Mengetik action yang mereferensikan state lain

store.tstypescript
interface TodoStore {
  todos: Todo[]
  filter: 'all' | 'active' | 'completed'
  addTodo: (text: string) => void
  toggleTodo: (id: string) => void
  filteredTodos: () => Todo[]
}

export const useTodoStore = create<TodoStore>()((set, get) => ({
  todos: [],
  filter: 'all',
  
  addTodo: (text) => set((state) => ({
    todos: [...state.todos, { id: crypto.randomUUID(), text, completed: false }]
  })),
  
  toggleTodo: (id) => set((state) => ({
    todos: state.todos.map((todo) =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    )
  })),
  
  filteredTodos: () => {
    const { todos, filter } = get()
    switch (filter) {
      case 'active': return todos.filter((t) => !t.completed)
      case 'completed': return todos.filter((t) => t.completed)
      default: return todos
    }
  }
}))

Derived state sebagai fungsi daripada getter menghindari nilai yang stale. Setiap panggilan ke filteredTodos() membaca state saat ini.

Memisahkan store untuk aplikasi besar

Pertanyaan interview yang umum menanyakan bagaimana menyusun Zustand untuk skala besar. Pola slice membagi store menjadi modul berdasarkan domain:

slices/authSlice.tstypescript
import { StateCreator } from 'zustand'

export interface AuthSlice {
  user: User | null
  isAuthenticated: boolean
  login: (credentials: Credentials) => Promise<void>
  logout: () => void
}

export const createAuthSlice: StateCreator<
  AuthSlice & CartSlice,  // Tipe store gabungan
  [],
  [],
  AuthSlice
> = (set) => ({
  user: null,
  isAuthenticated: false,
  login: async (credentials) => {
    const user = await authApi.login(credentials)
    set({ user, isAuthenticated: true })
  },
  logout: () => set({ user: null, isAuthenticated: false })
})
store.tstypescript
import { create } from 'zustand'
import { createAuthSlice, AuthSlice } from './slices/authSlice'
import { createCartSlice, CartSlice } from './slices/cartSlice'

export const useStore = create<AuthSlice & CartSlice>()((...args) => ({
  ...createAuthSlice(...args),
  ...createCartSlice(...args)
}))

Slice dapat mereferensikan satu sama lain melalui tipe store gabungan yang diteruskan ke StateCreator.

Pertanyaan Interview Umum dengan Jawaban Model

Kapan Zustand menjadi pilihan yang kurang tepat?

Zustand menambahkan kompleksitas tanpa manfaat dalam skenario berikut:

  • Data konfigurasi statis yang tidak pernah berubah saat runtime
  • State form yang dikelola oleh React Hook Form atau library serupa
  • Server state yang lebih baik ditangani oleh TanStack Query atau SWR
  • Prop passing parent-child sederhana dengan 2-3 level nesting

Bagian perbandingan di repository GitHub Zustand menyediakan perspektif maintainer tentang alternatif.

Bagaimana cara menguji component yang menggunakan Zustand?

Pengujian memerlukan reset state store antar test dan opsional mocking store sepenuhnya:

store.test.tstypescript
import { act, renderHook } from '@testing-library/react'
import { useCartStore } from './store'

beforeEach(() => {
  // Reset store ke state awal
  useCartStore.setState({ items: [], totalItems: 0 })
})

test('addItem increases cart count', () => {
  const { result } = renderHook(() => useCartStore())
  
  act(() => {
    result.current.addItem({ id: '1', name: 'Product', price: 10 })
  })
  
  expect(result.current.items).toHaveLength(1)
})

Untuk component test yang tidak boleh berinteraksi dengan store asli, mock di level modul:

Component.test.tsxtypescript
import { vi } from 'vitest'

vi.mock('./store', () => ({
  useCartStore: vi.fn(() => ({
    items: [{ id: '1', name: 'Mock Product', price: 25 }],
    addItem: vi.fn()
  }))
}))

Bagaimana Zustand menangani operasi async?

Berbeda dengan Redux, Zustand tidak memerlukan middleware untuk async. Action dapat langsung berupa fungsi async:

store.tstypescript
interface ProductStore {
  products: Product[]
  isLoading: boolean
  error: string | null
  fetchProducts: () => Promise<void>
}

export const useProductStore = create<ProductStore>((set) => ({
  products: [],
  isLoading: false,
  error: null,
  
  fetchProducts: async () => {
    set({ isLoading: true, error: null })
    try {
      const products = await productApi.getAll()
      set({ products, isLoading: false })
    } catch (err) {
      set({ error: err.message, isLoading: false })
    }
  }
}))

Untuk flow async yang kompleks, panduan pola async Zustand merekomendasikan menjaga state loading dan error terletak bersama dengan data yang dijelaskannya.

Perubahan Zustand v5 yang Mungkin Muncul di Interview

Zustand v5 memperkenalkan breaking changes yang digunakan interviewer untuk mengukur apakah kandidat mengikuti perkembangan terkini:

  • Tidak ada lagi default export: Import { create } bukan create
  • TypeScript lebih ketat: Pola create<T>()() menggantikan create<T>()
  • Hydration persist sinkron: Timing callback onRehydrateStorage berubah
  • Dukungan CJS dihapus: Package hanya ESM

Migrasi dari v4 ke v5 memerlukan pembaruan statement import dan penyesuaian kode yang bergantung pada timing hydration lama.

Poin Penting untuk Interview Zustand

  • Store Zustand berada di luar React tree, memungkinkan akses sinkron dan mencegah provider nesting
  • Selector dengan shallow comparison mengoptimalkan re-render untuk aplikasi production
  • Middleware persist memerlukan partialize untuk mengecualikan fungsi dari storage
  • Pola slice menskalakan Zustand ke aplikasi besar tanpa mengorbankan type safety
  • Action async bekerja langsung tanpa middleware, berbeda dengan pola Redux
  • Pengujian memerlukan reset state eksplisit antar test case
  • Server Components memaksa Zustand ke client boundary, memengaruhi keputusan arsitektur

Mulai berlatih!

Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

Tantangan harian

Bisakah kamu menemukan bug di React / Next.js?

Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Anthony Fillion-Maillet

Ditulis oleh

Anthony Fillion-Maillet

Pendiri SharpSkill

Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.

Diperbarui 25 Agustus 2026

Bagikan

Artikel terkait