REACT STATE YÖNETİMİ STRATEJİSİ SEÇMEK
"React'ta state yönetimi için ne kullanmalıyız?" sorusunun cevabı 2017'de basitti: Redux. 2024'te çok daha karmaşık. useState, useReducer, Context, Zustand, Jotai, Recoil, Redux Toolkit, MobX, React Query, SWR; her birinin yeri var. Yanlış seçim aşırı karmaşıklık veya yetersiz altyapı yaratır.
State yönetiminin sırrı: tek bir araç hepsini çözmez. Farklı state türleri farklı çözümler ister; useState ve useReducer gibi yerleşik araçların ne için tasarlandığını React öğrenme kaynakları üzerinden görmek, üçüncü parti kütüphane kararını da netleştirir. UI state, server state, URL state, form state, navigation state - hepsi farklı yaklaşım gerektirir.
Doğru state aracı sorusu, doğru state türü sorusunun gölgesidir: local UI state, paylaşılan client state ve server state ayrı dertlerdir ve ayrı araçlar ister. Tür ayrımı oturduğunda modern projelerin tipik mimarisi (useState + hafif global store + query kütüphanesi) kendiliğinden anlamlı hâle gelir.
State türleri
| State türü | Örnek | Tipik çözüm |
|---|---|---|
| Local UI state | Modal açık, form input | useState |
| Shared UI state | Theme, sidebar açık | Context veya Zustand |
| Server state | API'den gelen data | React Query |
| URL state | Filter, search query | URL params + router |
| Form state | Input değerleri, validation | React Hook Form |
| Global app state | Auth user, cart | Zustand / Redux |
useState: lokal state
Tek component'in kullandığı state. En basit, en hızlı.
function ModalButton() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>Aç</button>
{isOpen && <Modal onClose={() => setIsOpen(false)} />}
</>
);
}Ne zaman: state sadece bu component ve child'larında kullanılıyorsa.
useReducer: kompleks local state
State birden fazla değer içeriyor ve farklı action'lar tetikliyorsa.
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT': return { ...state, count: state.count + 1 };
case 'RESET': return { count: 0 };
case 'SET_NAME': return { ...state, name: action.payload };
default: return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0, name: '' });
return (
<>
<p>{state.count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
</>
);
}useState'ten daha "yapılandırılmış"; state logic component dışında bir reducer fonksiyonunda. Test kolay; complex state için uygun.
Context: paylaşılan state (az değişen)
Birden fazla component'in eriştiği state için. Ama performans açısından sınırlı.
const ThemeContext = createContext();
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Layout />
</ThemeContext.Provider>
);
}
function Header() {
const { theme } = useContext(ThemeContext);
return <header className={theme}>...</header>;
}Ne zaman: theme, locale, auth user gibi az değişen global state. Sık değişen state için Context kullanmak performans sorunu yaratır (her değişiklikte tüm consumer'lar re-render).
Zustand: modern global state
Redux'ın yerini alan basit, hafif kütüphane. 2024'te en popüler tercih.
import { create } from 'zustand';
const useCartStore = create((set) => ({
items: [],
addItem: (item) => set((state) => ({
items: [...state.items, item]
})),
removeItem: (id) => set((state) => ({
items: state.items.filter(i => i.id !== id)
})),
clear: () => set({ items: [] })
}));
// Component'te kullanım
function Cart() {
const items = useCartStore((state) => state.items);
const removeItem = useCartStore((state) => state.removeItem);
return (
<ul>
{items.map(item => (
<li key={item.id}>
{item.name}
<button onClick={() => removeItem(item.id)}>Sil</button>
</li>
))}
</ul>
);
}Avantajları:
- Boilerplate minimal
- TypeScript desteği mükemmel
- Selector ile sadece kullanılan state'i izle (re-render optimizasyonu)
- Provider gerekmez; doğrudan import et kullan
- Bundle size ~1 KB
Redux Toolkit: kurumsal global state
Redux modern hali. Boilerplate azaltılmış ama hâlâ Zustand'dan daha verbose.
import { createSlice, configureStore } from '@reduxjs/toolkit';
const cartSlice = createSlice({
name: 'cart',
initialState: { items: [] },
reducers: {
addItem: (state, action) => { state.items.push(action.payload); },
removeItem: (state, action) => {
state.items = state.items.filter(i => i.id !== action.payload);
}
}
});
export const { addItem, removeItem } = cartSlice.actions;
export const store = configureStore({ reducer: { cart: cartSlice.reducer } });Ne zaman: çok büyük takım, complex state mantığı, time-travel debugging gerektiği, mevcut Redux projesi olduğu durumlarda. Yeni projeler için çoğunlukla overkill.
React Query: server state
API'den gelen veri için ayrı bir araç gerek. useState ile yapılan boilerplate kodu temizler.
import { useQuery } from '@tanstack/react-query';
function ProductList() {
const { data, isLoading } = useQuery({
queryKey: ['products'],
queryFn: fetchProducts
});
if (isLoading) return <p>Yükleniyor...</p>;
return <ul>{data.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}Server state için detaylar React Query ile server state yönetmek sayfasında.
URL state: router params
Bazı state URL'de tutulmalı. Filter, search query, pagination paylaşılabilir/bookmarklanabilir olmalı.
import { useSearchParams } from 'react-router-dom';
function ProductList() {
const [searchParams, setSearchParams] = useSearchParams();
const filter = searchParams.get('filter') || 'all';
const page = Number(searchParams.get('page')) || 1;
return (
<>
<select
value={filter}
onChange={(e) => setSearchParams({ filter: e.target.value, page: '1' })}
>
<option value="all">Tümü</option>
<option value="active">Aktif</option>
</select>
</>
);
}Avantaj: kullanıcı URL'i kopyalayıp paylaşabilir; sayfa yenilense bile state korunur; tarayıcı geri/ileri butonları çalışır.

Karar matrisi
Sadece bir component kullanıyor mu?
- Evet → useState
- Hayır → sonraki soru
API'dan mı geliyor?
- Evet → React Query
- Hayır → sonraki soru
URL'de tutulabilir mi (filter, search)?
- Evet → URL params + router
- Hayır → sonraki soru
Sık değişiyor mu?
- Hayır (theme, locale) → Context
- Evet → Zustand (veya Redux Toolkit büyük takımlar için)
Modern proje state mimarisi
Tipik bir modern React projesi şu kombinasyonu kullanır:
- useState: Local UI state (modal, dropdown, input)
- React Hook Form: Form state
- React Query: Server state (products, users, posts)
- URL params: Filter, pagination, search
- Zustand: Global UI state (cart, theme, auth)
- Context: Sadece çok az değişen şeyler (i18n)
Redux yok; ama büyük kurumsal projelerde Zustand yerine Redux Toolkit kullanılabilir.
State management yaygın hataları
- Her şeyi global yapmak. Local state global'e çekmek karmaşıklık ekler
- Server state'i global state'e koymak. Cache, refetch, sync problemleri; React Query daha iyi
- Context'i sık değişen state için kullanmak. Performance felaketi
- useState yerine useReducer'ı her yerde kullanmak. Basit state için overkill
- Form için Redux kullanmak. React Hook Form daha uygun
- URL'de tutulabilecek state'i Redux'a koymak. URL daha basit ve paylaşılabilir
State lifting
İki component'in aynı state'e ihtiyacı varsa state ortak parent'a taşınır.
// Yanlış: iki component'te ayrı state
function App() {
return (
<>
<Search /> {/* kendi state'i */}
<Results /> {/* kendi state'i */}
</>
);
}
// Doğru: state parent'ta
function App() {
const [query, setQuery] = useState('');
return (
<>
<Search query={query} onChange={setQuery} />
<Results query={query} />
</>
);
}State lifting tipik ilk adım. Çok yukarı çıkarsa Zustand'a alınır; çok aşağıdaysa prop drilling sorunu olabilir, Context çözer.
State persisting (localStorage)
Sayfa yenilense bile korunması gereken state için localStorage.
// Zustand ile
import { persist } from 'zustand/middleware';
const useStore = create(
persist(
(set) => ({
theme: 'light',
setTheme: (theme) => set({ theme })
}),
{
name: 'app-storage'
}
)
);Tek satırla state otomatik localStorage'a kaydedilir; sayfa açıldığında geri yüklenir. React Query persistance plugin'i de var.

İleri Adımlar
State yönetimi modern React'ın en stratejik kararlarından. Pratiği sürekli biçimde geliştirmek için kapsamlı React eğitimi programları hooks ve state mimarisi konularını birlikte aktarır.
Toparlarsak
React state yönetimi tek bir araç değil; state türüne göre seçim. useState lokal UI, useReducer kompleks lokal, Context az değişen paylaşılan, Zustand global UI, React Query server, URL params paylaşılabilir state için. Modern proje karması bunların kombinasyonu. Redux artık yeni projeler için varsayılan değil; Zustand çoğu durum için yeterli. Her şeyi global yapmak en yaygın hata; doğru araç doğru yerde kullanılmalı.



