Zustand Mülakat Soruları 2026: React State Yönetimi ve En İyi Pratikler

2026 yılı Zustand mülakat sorularına hazırlanın. React state yönetimi, Context API karşılaştırması, middleware kullanımı ve TypeScript entegrasyonunu öğrenin.

Zustand Mülakat Soruları 2026: React State Yönetimi ve En İyi Pratikler

Zustand, Context API'den fazlasına ihtiyaç duyan ancak Redux kadar karmaşıklık istemeyen React uygulamaları için tercih edilen state yönetim kütüphanesi haline gelmiştir. Minimal API yüzeyi ve TypeScript odaklı tasarımı sayesinde, Zustand soruları artık frontend mülakatlarında düzenli olarak karşımıza çıkmaktadır, özellikle mid-level ve senior React pozisyonlarında.

Mülakatçıların Beklentileri

Zustand mülakat soruları üç alanı test eder: store pattern ile React'ın yerleşik state yapısı arasındaki farkı anlama, Zustand'ın alternatiflere göre ne zaman daha iyi performans gösterdiğini bilme ve store'ları sürdürülebilirlik açısından yapılandırma becerisi.

Her Adayın Bilmesi Gereken Temel Zustand Kavramları

2024'ün sonlarında yayınlanan Zustand v5, v4'e göre birçok önemli değişiklik getirmiştir. create fonksiyonu artık ayrı bir useStore çağrısı gerektirmemekte ve persist middleware varsayılan olarak senkron hydration modeli kullanmaktadır. Mülakatçılar adayların güncel API'yi bilmesini beklemektedir.

Zustand'ı useState ve useReducer'dan ayıran nedir?

Zustand store'ları React bileşen ağacının dışında bulunur. Bu mimari fark üç pratik sonuç doğurur:

  1. State, Context provider'lara ihtiyaç duymadan bileşen mount ve unmount işlemleri arasında kalıcıdır
  2. Güncellemeler üst bileşenlerin yeniden render edilmesine neden olmaz, yalnızca abone olan bileşenler yeniden render edilir
  3. State, React dışında senkron olarak erişilebilir, bu da event handler'lar ve asenkron mantık için kullanışlıdır
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)
}))

get fonksiyonu mevcut state'e senkron erişim sağlar ve useState ile yaygın olan stale closure sorununu önler.

Zustand yeniden render'ları nasıl yönetir?

Zustand varsayılan olarak shallow equality kullanır. Bir bileşen useCartStore() ile bir store'a abone olduğunda, tüm state nesnesini alır ve herhangi bir değişiklikte yeniden render edilir. Belirli slice'ları seçmek gereksiz render'ları önler:

Component.tsxtypescript
// Kötü: herhangi bir store değişikliğinde yeniden render edilir
const { items } = useCartStore()

// İyi: yalnızca items değiştiğinde yeniden render edilir
const items = useCartStore((state) => state.items)

// Birden fazla değer: shallow karşılaştırma kullanın
import { shallow } from 'zustand/shallow'

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

zustand/shallow'dan gelen shallow comparator, nesnenin kendisi yerine nesne özelliklerinde referans eşitliği kontrolü yapar.

Zustand vs Context API: Hangisini Ne Zaman Seçmeli

Bu karşılaştırma sorusu, state yönetimini kapsayan neredeyse her mülakatta karşımıza çıkar. Cevap, güncelleme sıklığına ve state karmaşıklığına bağlıdır.

KriterContext APIZustand
Bundle boyutu0 KB (yerleşik)1.2 KB gzipped
Render kontrolümemo/useMemo ile manuelYerleşik selector'lar
DevToolsYalnızca React DevToolsRedux DevTools uyumlu
Server componentsTam destekClient boundary gerektirir
Asenkron stateWrapper gerektirirNative destek

Context API, tema veya locale gibi seyrek değişen değerler için iyi çalışır. Zustand, form input'ları, gerçek zamanlı veriler veya alışveriş sepetleri gibi sık state güncellemelerinin olduğu durumlarda üstündür.

Server Components Değerlendirmesi

Zustand store'ları "use client" direktifini gerektirir. React Server Components'ı yoğun kullanan uygulamalar için bu, Zustand state'inin yalnızca client bileşenlerinde yaşadığı anlamına gelir. Hibrit mimariler genellikle sunucudan getirilen verileri props olarak client bileşenlerine iletir ve bu bileşenler daha sonra Zustand ile senkronize olur.

Zustand'da Middleware Desenleri

Middleware soruları, adayın konfigürasyon yerine kompozisyonu anlayıp anlamadığını test eder. Zustand middleware, temel API'yi değiştirmeden davranış ekleyerek store oluşturucu fonksiyonunu sarar.

Persist middleware nasıl çalışır?

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 })
    }
  )
)

partialize seçeneği fonksiyonları ve türetilmiş state'i kalıcılıktan hariç tutar. Bu olmadan serializasyon başarısız olur veya storage gereksiz verilerle şişer.

Birden fazla middleware'i birleştirme

Middleware içten dışa doğru compose edilir. En içteki middleware ilk olarak çalıştırılır:

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 ve action'lar
        }))
      ),
      { name: 'app-storage' }
    ),
    { name: 'AppStore' }
  )
)

immer middleware, immutable state üreten mutable tarzı güncellemeleri etkinleştirir. subscribeWithSelector middleware, React bileşenleri dışında state slice'larına abone olmayı sağlar.

React / Next.js mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

TypeScript Entegrasyon Desenleri

Zustand v5, TypeScript çıkarımını önemli ölçüde iyileştirmiştir. Çift fonksiyon çağrısı deseni create<Type>()(), middleware zincirleri için tam tip çıkarımı sağlar.

Diğer state'e referans veren action'ları tipleme

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
    }
  }
}))

Türetilmiş state'i getter'lar yerine fonksiyon olarak tanımlamak eski değerlerden kaçınır. Her filteredTodos() çağrısı güncel state'i okur.

Büyük uygulamalar için store'ları bölme

Yaygın bir mülakat sorusu, ölçeklenebilirlik için Zustand'ın nasıl yapılandırılacağını sorar. Slice deseni, bir store'u domain modüllerine böler:

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,  // Birleştirilmiş store tipi
  [],
  [],
  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'lar, StateCreator'a iletilen birleştirilmiş store tipi aracılığıyla birbirine referans verebilir.

Örnek Cevaplarla Yaygın Mülakat Soruları

Zustand ne zaman kötü bir tercih olur?

Zustand bu senaryolarda fayda sağlamadan karmaşıklık ekler:

  • Çalışma zamanında hiç değişmeyen statik konfigürasyon verileri
  • React Hook Form veya benzer kütüphaneler tarafından yönetilen form state'i
  • TanStack Query veya SWR tarafından daha iyi yönetilen sunucu state'i
  • 2-3 seviye iç içe geçmeyle basit parent-child prop aktarımı

Zustand kullanan bileşenler nasıl test edilir?

Test, testler arasında store state'inin sıfırlanmasını ve isteğe bağlı olarak tüm store'un mock'lanmasını gerektirir:

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

beforeEach(() => {
  // Store'u başlangıç state'ine sıfırla
  useCartStore.setState({ items: [], totalItems: 0 })
})

test('addItem sepet sayısını artırır', () => {
  const { result } = renderHook(() => useCartStore())
  
  act(() => {
    result.current.addItem({ id: '1', name: 'Product', price: 10 })
  })
  
  expect(result.current.items).toHaveLength(1)
})

Gerçek store'larla etkileşime girmemesi gereken bileşen testleri için modül seviyesinde mock yapın:

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

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

Zustand asenkron işlemleri nasıl yönetir?

Redux'tan farklı olarak, Zustand async için middleware gerektirmez. Action'lar doğrudan async fonksiyonlar olabilir:

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 })
    }
  }
}))

Karmaşık asenkron akışlar için, loading ve error state'lerinin tanımladıkları verilerle birlikte tutulması önerilir.

Mülakatlarda Karşılaşılabilecek Zustand v5 Değişiklikleri

Zustand v5, mülakatçıların adayların güncel olup olmadığını değerlendirmek için kullandığı önemli değişiklikler getirmiştir:

  • Varsayılan export yok: create yerine { create } import edin
  • Daha katı TypeScript: create<T>()() deseni create<T>()'yi değiştirir
  • Senkron persist hydration: onRehydrateStorage callback zamanlaması değişti
  • CJS desteği kaldırıldı: Yalnızca ESM paketi

v4'ten v5'e geçiş, import ifadelerinin güncellenmesini ve eski hydration zamanlamasına dayanan kodun ayarlanmasını gerektirir.

Zustand Mülakatları İçin Temel Çıkarımlar

  • Zustand store'ları React ağacının dışında yaşar, senkron erişim sağlar ve provider iç içe geçmesini önler
  • Shallow karşılaştırmalı selector'lar üretim uygulamaları için yeniden render'ları optimize eder
  • Persist middleware, fonksiyonları storage'dan hariç tutmak için partialize gerektirir
  • Slice deseni, tip güvenliğinden ödün vermeden Zustand'ı büyük uygulamalara ölçeklendirir
  • Async action'lar, Redux desenlerinin aksine middleware olmadan doğrudan çalışır
  • Test, test senaryoları arasında açık state sıfırlaması gerektirir
  • Server Components, Zustand'ı client sınırlarına zorlar ve mimari kararları etkiler

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Günün meydan okuması

React / Next.js kodundaki hatayı bulabilir misin?

Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

25 Ağustos 2026 tarihinde güncellendi

Paylaş

İlgili makaleler