React Hooks, fonksiyonel bileşenlerde state yönetimi ve yaşam döngüsü özelliklerini kullanmamızı sağlayan güçlü bir özelliktir. Bu yazıda, React Hooks'un en iyi kullanım pratiklerini ve performans optimizasyonu için önemli ipuçlarını inceleyeceğiz.
useState Hook'u ve Re-render Optimizasyonu
useState
hook'u, fonksiyonel bileşenlerde state yönetimi için en temel araçtır. Ancak yanlış kullanımı gereksiz re-render'lara yol açabilir.
// ❌ Yanlış Kullanım const [user, setUser] = useState({ name: 'John', age: 25, preferences: { theme: 'dark', notifications: true } }); // Nested state güncellemesi setUser({ ...user, preferences: { ...user.preferences, theme: 'light' } }); // ✅ Doğru Kullanım const [user, setUser] = useState({ name: 'John', age: 25 }); const [preferences, setPreferences] = useState({ theme: 'dark', notifications: true }); // State'leri ayrı ayrı yönetmek setPreferences(prev => ({ ...prev, theme: 'light' }));
useEffect Hook'u ve Bağımlılık Dizisi
useEffect
hook'u yan etkileri yönetmek için kullanılır, ancak bağımlılık dizisinin yanlış kullanımı sonsuz döngülere veya eksik güncellemelere neden olabilir.
// ❌ Yanlış Kullanım useEffect(() => { fetchUserData(userId); }, []); // Eksik bağımlılık // ✅ Doğru Kullanım useEffect(() => { fetchUserData(userId); }, [userId]); // userId değiştiğinde effect tetiklenir // 🚀 İleri Seviye Kullanım useEffect(() => { const controller = new AbortController(); async function fetchData() { try { const response = await fetch(`/api/users/${userId}`, { signal: controller.signal }); const data = await response.json(); setUser(data); } catch (error) { if (!error.name === 'AbortError') { setError(error); } } } fetchData(); return () => controller.abort(); // Cleanup }, [userId]);
useMemo ve useCallback ile Performans Optimizasyonu
Gereksiz hesaplamaları ve re-render'ları önlemek için useMemo
ve useCallback
hook'larını kullanabiliriz.
// ❌ Yanlış Kullanım const sortedItems = items.sort((a, b) => b.value - a.value); // ✅ Doğru Kullanım - useMemo const sortedItems = useMemo(() => { return items.sort((a, b) => b.value - a.value); }, [items]); // ❌ Yanlış Kullanım const handleSearch = (query) => { setSearchResults(items.filter(item => item.name.toLowerCase().includes(query.toLowerCase()) )); }; // ✅ Doğru Kullanım - useCallback const handleSearch = useCallback((query) => { setSearchResults(items.filter(item => item.name.toLowerCase().includes(query.toLowerCase()) )); }, [items]);
Custom Hooks ile Kod Tekrarını Önleme
Tekrar eden mantığı custom hook'lar içinde soyutlayarak kod tekrarını önleyebilir ve bakımı kolaylaştırabiliriz.
// ✅ Custom Hook Örneği 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 = useCallback((value) => { try { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); window.localStorage.setItem(key, JSON.stringify(valueToStore)); } catch (error) { console.error(error); } }, [key, storedValue]); return [storedValue, setValue]; } // Kullanımı function App() { const [theme, setTheme] = useLocalStorage('theme', 'light'); return ( <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}> Temayı Değiştir </button> ); }
useReducer ile Kompleks State Yönetimi
Karmaşık state mantığını yönetmek için useReducer
hook'unu kullanabiliriz.
// Action Types const ADD_TODO = 'ADD_TODO'; const TOGGLE_TODO = 'TOGGLE_TODO'; const DELETE_TODO = 'DELETE_TODO'; // Reducer function todoReducer(state, action) { switch (action.type) { case ADD_TODO: return [...state, { id: Date.now(), text: action.payload, completed: false }]; case TOGGLE_TODO: return state.map(todo => todo.id === action.payload ? { ...todo, completed: !todo.completed } : todo ); case DELETE_TODO: return state.filter(todo => todo.id !== action.payload); default: return state; } } // Component function TodoList() { const [todos, dispatch] = useReducer(todoReducer, []); const addTodo = (text) => { dispatch({ type: ADD_TODO, payload: text }); }; const toggleTodo = (id) => { dispatch({ type: TOGGLE_TODO, payload: id }); }; const deleteTodo = (id) => { dispatch({ type: DELETE_TODO, payload: id }); }; return ( // JSX ); }
Sonuç
React Hooks, modern React uygulamalarının vazgeçilmez bir parçasıdır. Doğru kullanıldığında, kodunuzu daha temiz, bakımı kolay ve performanslı hale getirebilirsiniz. Bu yazıda bahsedilen best practice'leri uygulayarak, daha iyi React uygulamaları geliştirebilirsiniz.
Önemli noktaları özetleyelim:
- State'leri mantıklı bir şekilde bölün
- Effect'lerin bağımlılıklarını doğru yönetin
- Gereksiz hesaplamaları
useMemo
veuseCallback
ile optimize edin - Tekrar eden mantığı custom hook'lar ile soyutlayın
- Karmaşık state yönetimi için
useReducer
kullanın
React Hooks hakkında daha fazla bilgi için React resmi dokümantasyonunu inceleyebilirsiniz.