React Hooks: Modern React Geliştirmenin Temelleri
React Hooks'ların nasıl çalıştığını, en yaygın kullanım senaryolarını ve best practice'leri öğrenin. useState, useEffect, useContext ve custom hooks örnekleriyle birlikte.
React Hooks: Modern React Geliştirmenin Temelleri
React Hooks, React 16.8 ile gelen ve fonksiyonel bileşenlerde state yönetimi ve side effect'leri kolaylaştıran özelliklerdir. Bu yazıda, en yaygın kullanılan hooks'ları ve best practice'leri inceleyeceğiz.
Hooks Nedir?
Hooks, fonksiyonel bileşenlerde state ve diğer React özelliklerini kullanmanızı sağlayan özel fonksiyonlardır. Class component'lerin karmaşıklığını ortadan kaldırır ve kodun daha okunabilir olmasını sağlar.
Temel Hooks
1. useState
useState
hook'u, fonksiyonel bileşenlerde state yönetimi için kullanılır:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Sayı: {count}</p>
<button onClick={() => setCount(count + 1)}>
Artır
</button>
</div>
);
}
2. useEffect
useEffect
hook'u, side effect'leri yönetmek için kullanılır:
import React, { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUser() {
try {
const response = await fetch(`/api/users/${userId}`);
const userData = await response.json();
setUser(userData);
} catch (error) {
console.error('Kullanıcı yüklenemedi:', error);
} finally {
setLoading(false);
}
}
fetchUser();
}, [userId]); // userId değiştiğinde effect tekrar çalışır
if (loading) return <div>Yükleniyor...</div>;
if (!user) return <div>Kullanıcı bulunamadı</div>;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
İleri Seviye Hooks
3. useContext
useContext
hook'u, prop drilling'i önlemek için global state yönetimi sağlar:
// ThemeContext.js
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
// App.js
function App() {
return (
<ThemeProvider>
<Header />
<Main />
</ThemeProvider>
);
}
// Header.js
function Header() {
const { theme, setTheme } = useTheme();
return (
<header className={theme}>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Tema Değiştir
</button>
</header>
);
}
4. useReducer
Karmaşık state yönetimi için useReducer
kullanılır:
import React, { useReducer } from 'react';
const initialState = {
count: 0,
history: []
};
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return {
...state,
count: state.count + 1,
history: [...state.history, state.count]
};
case 'DECREMENT':
return {
...state,
count: state.count - 1,
history: [...state.history, state.count]
};
case 'RESET':
return initialState;
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Sayı: {state.count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>
Artır
</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>
Azalt
</button>
<button onClick={() => dispatch({ type: 'RESET' })}>
Sıfırla
</button>
<div>
<h4>Geçmiş:</h4>
<ul>
{state.history.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
</div>
</div>
);
}
Custom Hooks
Kendi hook'larınızı oluşturarak kod tekrarını önleyebilirsiniz:
// useLocalStorage.js
import { useState, useEffect } from 'react';
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
const setValue = (value) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(error);
}
};
return [storedValue, setValue];
}
// Kullanım
function App() {
const [name, setName] = useLocalStorage('name', '');
return (
<div>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Adınızı girin"
/>
</div>
);
}
Best Practices
1. Hook Kuralları
- Hooks'ları sadece React fonksiyonlarında kullanın
- Hooks'ları sadece en üst seviyede çağırın
- Hooks'ları sadece React fonksiyonlarında çağırın
2. useEffect Dependency Array
// ❌ Yanlış - sonsuz döngü
useEffect(() => {
fetchData();
});
// ✅ Doğru - sadece component mount olduğunda
useEffect(() => {
fetchData();
}, []);
// ✅ Doğru - dependency değiştiğinde
useEffect(() => {
fetchData();
}, [userId]);
3. Custom Hook Naming
Custom hook'larınızı use
ile başlatın:
// ✅ Doğru
function useCounter() { ... }
function useLocalStorage() { ... }
function useApi() { ... }
// ❌ Yanlış
function counter() { ... }
function localStorage() { ... }
Performans Optimizasyonu
useMemo ve useCallback
import React, { useMemo, useCallback } from 'react';
function ExpensiveComponent({ items, filter }) {
// Pahalı hesaplama
const filteredItems = useMemo(() => {
return items.filter(item => item.includes(filter));
}, [items, filter]);
// Callback fonksiyonu
const handleClick = useCallback((id) => {
console.log('Item clicked:', id);
}, []);
return (
<div>
{filteredItems.map(item => (
<button key={item} onClick={() => handleClick(item)}>
{item}
</button>
))}
</div>
);
}
Sonuç
React Hooks, modern React geliştirmenin temelidir. Doğru kullanıldığında:
- ✅ Daha temiz ve okunabilir kod
- ✅ Daha az boilerplate
- ✅ Daha iyi performans
- ✅ Daha kolay test edilebilirlik
sağlar. Hooks'ları öğrenmek ve doğru kullanmak, React geliştiricisi olarak kariyerinizde büyük fark yaratacaktır.
Kaynaklar
Bu yazı React Hooks konusunda size rehberlik etmeyi amaçlamaktadır. Sorularınız için yorum bırakabilirsiniz!