React bileşenlerinde aynı state mantığını tekrar tekrar yazmak yerine, custom hook'lar sayesinde bu mantığı yeniden kullanılabilir fonksiyonlara taşıyabilirsiniz. Peki, sıfırdan bir custom hook nasıl yazılır? İşte adım adım rehber.
Custom Hook Nedir ve Neden Kullanılır?
Custom hook, React'in built-in hook'larını (useState, useEffect, useReducer vb.) kullanarak oluşturduğunuz, use ile başlayan bir JavaScript fonksiyonudur. Amaç, bileşenler arasında state mantığını paylaşmaktır. Örneğin, bir API'den veri çeken iki farklı bileşeniniz varsa, bu mantığı tek bir useFetch hook'unda toplayabilirsiniz. Bu sayede kod tekrarı azalır, test edilebilirlik artar ve projeniz daha modüler hale gelir. React'in kendi hook'larını kullanarak custom hook yazmak, useState ve useReducer arasındaki farkları anlamayı da gerektirir.
Adım Adım Custom Hook Oluşturma
- İhtiyacı Belirleyin: Hangi state mantığının birden fazla bileşende kullanıldığını tespit edin. Örneğin, form girişleri, API çağrıları, localStorage işlemleri veya pencere boyutu takibi.
- Hook Dosyasını Oluşturun: Projenizde
hooksadlı bir klasör açın ve hook'unuz için bir dosya oluşturun. Adlandırma kuralı:useHookAdı.jsveya.ts. - Hook Fonksiyonunu Yazın: Dosyada,
useile başlayan bir fonksiyon tanımlayın. Bu fonksiyon, gerekli parametreleri alır ve gerekli React hook'larını kullanır. Örneğin:import { useState, useEffect } from 'react'; export function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { setLoading(true); fetch(url) .then(res => { if (!res.ok) throw new Error('HTTP error'); return res.json(); }) .then(data => { setData(data); setError(null); }) .catch(err => setError(err.message)) .finally(() => setLoading(false)); }, [url]); return { data, loading, error }; } - Hook'u Bileşenlerde Kullanın: Custom hook'unuzu bir bileşene import ederek, dönen değerleri kullanın. Aynı hook farklı URL'lerle çağrılabilir.
import { useFetch } from './hooks/useFetch'; function UserList() { const { data, loading, error } = useFetch('/api/users'); if (loading) return <p>Yükleniyor...</p> if (error) return <p>Hata: {error}</p> return ( <ul> {data.map(user => <li key={user.id}>{user.name}</li>)} </ul> ); } - Parametre ve Dönüş Türlerini Belirleyin: TypeScript kullanıyorsanız, hook'unuzu tip güvenli hale getirin. Parametreler ve dönüş değerleri için interface veya type tanımlayın.
- Yan Etkileri Temizleyin: Eğer hook'unuzda bir
useEffectaboneliği varsa (örn. event listener, interval), mutlaka cleanup fonksiyonu yazın. Aksi halde bellek sızıntıları oluşabilir. React useEffect Cleanup: Adım Adım Bellek Sızıntılarını Önleme Rehberi bu konuda detaylı bilgi sunar. - Hook'u Test Edin: Custom hook'larınızı
renderHookile test edin. Örneğin,useFetch'in başarılı ve başarısız senaryolarını test edebilirsiniz.
Örnek: useLocalStorage Hook'u
Aşağıdaki örnekte, localStorage ile senkronize çalışan bir state hook'u oluşturuyoruz:
import { useState, useEffect } from 'react';
export 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;
}
});
useEffect(() => {
try {
window.localStorage.setItem(key, JSON.stringify(storedValue));
} catch (error) {
console.error(error);
}
}, [key, storedValue]);
return [storedValue, setStoredValue];
}
Bu hook, hem state'i günceller hem de localStorage'u otomatik olarak günceller. Farklı bileşenlerde aynı anahtarla kullanıldığında veri tutarlılığı sağlanır.
Sık Yapılan Hatalar ve Dikkat Edilmesi Gerekenler
- Hook'ları Koşullu Olarak Çağırmayın: React hook'ları her render'da aynı sırada çağrılmalıdır. Custom hook içinde dahi olsa,
if-elseiçinde hook çağırmayın. - Bağımlılıkları Doğru Ayarlayın:
useEffectbağımlılık dizisini eksik veya fazla belirlemek, performans sorunlarına veya hatalara yol açar. ESLint eklentilerini kullanın. - Gereksiz State Kullanmayın: Derived state (türetilmiş durum) için
useMemokullanın. Custom hook içinde state'e ihtiyaç yoksa, sadece useEffect veya useCallback kullanabilirsiniz. - İsimlendirmeye Dikkat Edin: Hook'unuz
useile başlamalıdır, aksi halde React lint kuralları uyarı verebilir.
Custom Hook vs Higher-Order Component (HOC)
Custom hook'lar, HOC'lere göre daha okunabilir ve daha az iç içe geçme (wrapping) gerektirir. Ayrıca TypeScript ile uyumları daha iyidir. Günümüz React projelerinde state mantığını paylaşmanın önerilen yolu custom hook'lardır. Daha karmaşık state yönetimi için useState ve useReducer karşılaştırması size yol gösterebilir.
Sonuç
Custom hook'lar, React projelerinizde kod tekrarını azaltmak ve bileşen mantığını temiz tutmak için güçlü bir araçtır. Yukarıdaki adımları takip ederek kendi hook'larınızı oluşturabilir, projenizin sürdürülebilirliğini artırabilirsiniz. Unutmayın, her custom hook bir problem çözmelidir; gereksiz yere soyutlama yapmaktan kaçının.
Sık Sorulan Sorular
Custom hook nedir ve ne zaman kullanılır?
Custom hook, React'in built-in hook'larını kullanarak yazılan ve 'use' ile başlayan bir fonksiyondur. Birden fazla bileşende aynı state mantığını kullanmanız gerektiğinde (örneğin API çağrıları, form yönetimi) custom hook oluşturarak kod tekrarını önleyebilirsiniz.
Custom hook nasıl test edilir?
React Testing Library'nin renderHook fonksiyonunu kullanarak custom hook'ları test edebilirsiniz. Hook'un döndürdüğü değerleri ve yan etkilerini, farklı senaryolar altında doğrulayabilirsiniz.
Custom hook içinde useState kullanmak zorunlu mu?
Hayır, custom hook içinde React hook'larından herhangi birini kullanabilirsiniz veya hiçbirini kullanmayabilirsiniz. Örneğin, sadece useEffect içeren bir hook yazabilirsiniz. Ancak 'use' önekiyle başlamalıdır.






