React Hooks: Modern React Geliştirmenin Temel Taşları
React, 2019 yılında Hooks API'sini tanıttığında frontend dünyasında köklü bir değişim yaşandı. Sınıf tabanlı bileşenlerin karmaşıklığından sıyrılıp fonksiyonel bileşenlerin sadeliğine geçiş, yalnızca bir sözdizimi değişikliği değildi; aynı zamanda state yönetimi, yaşam döngüsü ve yan etkileri ele alma biçimimizi baştan aşağı dönüştürdü. Bugün React ekosisteminde Hooks, modern uygulama geliştirmenin vazgeçilmez bir parçası haline geldi.
Bu rehberde React Hooks'un ne olduğunu, neden bu kadar önemli olduğunu ve günlük geliştirme pratiğinde nasıl etkili biçimde kullanılacağını kapsamlı şekilde ele alacağız.
React Hooks Nedir ve Neden Ortaya Çıktı?
Hooks, fonksiyonel bileşenlerin içinden React'in state ve yaşam döngüsü özelliklerine erişmenizi sağlayan fonksiyonlardır. Kısaca söylemek gerekirse, sınıf yazmadan React'in tüm gücünden yararlanmanıza olanak tanır.
React ekibinin Hooks'u sunmasının arkasında birkaç somut neden vardı:
- Karmaşık bileşenlerin yönetimi zorlaşmıştı. Bir bileşen büyüdükçe,
componentDidMount,componentDidUpdatevecomponentWillUnmountgibi yaşam döngüsü metotları birbiriyle ilgisiz mantıkları aynı yere yığıyordu. - Mantığı yeniden kullanmak güçtü.
render propsvehigher-order componentsgibi kalıplar, iç içe geçmiş "sarmalayıcı cehennemi" yaratıyordu. - Sınıflar insanlar için kafa karıştırıcıydı.
thisbağlamı, binding kuralları ve sınıf alanları yeni geliştiriciler için ciddi bir öğrenme engeli oluşturuyordu.
Hooks, bu sorunların tamamına aynı anda çözüm getirdi: mantığı bileşenden bağımsız olarak yeniden kullanılabilir hale getirdi, ilgili kodu bir arada tuttu ve fonksiyonel programlamanın sadeliğini React'e taşıdı.
Hooks'un Temel Kuralları
Hooks kullanmaya başlamadan önce iki kritik kuralı içselleştirmeniz gerekir. Bu kurallar, React'in Hooks'u doğru şekilde eşleştirebilmesi için hayatidir.
- Hooks yalnızca en üst seviyede çağrılmalıdır. Döngüler, koşullar veya iç içe fonksiyonlar içinde Hook çağıramazsınız. React, Hook'ların çağrılma sırasına göre state'i takip eder; koşullu çağrılar bu sırayı bozar.
- Hooks yalnızca React fonksiyonlarından çağrılmalıdır. Ya bir fonksiyonel bileşenin içinde ya da özel bir Hook'un içinde kullanılmalıdır. Normal JavaScript fonksiyonlarında Hook çağırmak yasaktır.
Bu kurallara uyumu kolaylaştırmak için eslint-plugin-react-hooks paketini projenize eklemenizi şiddetle tavsiye ederim.
En Sık Kullanılan Yerleşik Hook'lar
React'in sunduğu yerleşik Hook'lar, günlük geliştirmenin bel kemiğini oluşturur. En yaygın kullanılanları tek tek inceleyelim.
useState: Bileşen State'i Yönetmek
useState, fonksiyonel bileşenlere yerel state eklemenin en basit yoludur. Bir başlangıç değeri alır ve iki elemanlı bir dizi döndürür: mevcut değer ve onu güncelleyen fonksiyon.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Sayaç: {count}</p>
<button onClick={() => setCount(count + 1)}>Artır</button>
</div>
);
}
Dikkat edilmesi gereken bir nokta: state güncellemeleri asenkron olduğundan, önceki değere dayalı güncellemelerde fonksiyonel formu kullanmak daha güvenlidir.
setCount(prev => prev + 1);
useEffect: Yan Etkileri Yönetmek
useEffect, veri çekme, abonelik kurma, DOM'u doğrudan manipüle etme gibi yan etkileri yönetmek için kullanılır. Sınıf bileşenlerindeki componentDidMount, componentDidUpdate ve componentWillUnmount üçlüsünün yerini alır.
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
let isMounted = true;
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => {
if (isMounted) setUser(data);
});
return () => {
isMounted = false;
};
}, [userId]);
if (!user) return <p>Yükleniyor...</p>;
return <h2>{user.name}</h2>;
}
İkinci parametre olan bağımlılık dizisi kritik önem taşır:
- Boş dizi
[]: Efekt yalnızca bileşen mount edildiğinde bir kez çalışır. - Değer içeren dizi
[userId]: İlgili değer değiştiğinde efekt yeniden çalışır. - Dizi yok: Efekt her render'da çalışır; genellikle istenmeyen bir durumdur.
useContext: Global Veriye Erişim
useContext, React Context API'sini fonksiyonel bileşenlerden okumanın temiz yoludur. Tema, dil veya kullanıcı bilgisi gibi geniş kapsamlı verileri prop drilling yapmadan paylaşmanızı sağlar.
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Tıkla</button>;
}
useRef: Değerleri Saklamak ve DOM'a Erişmek
useRef, render'lar arasında kalıcı bir değer tutar ancak state'in aksine değiştiğinde yeniden render tetiklemez. DOM elemanlarına doğrudan erişmek için de sıkça kullanılır.
import { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
return (
<>
<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Odaklan</button>
</>
);
}
useMemo ve useCallback: Performans Optimizasyonu
Bu iki Hook, gereksiz hesaplamaları ve referans değişimlerini önlemek için kullanılır.
useMemo: Pahalı bir hesaplamanın sonucunu, bağımlılıklar değişmediği sürece önbelleğe alır.useCallback: Bir fonksiyonun referansını, bağımlılıklar değişmediği sürece sabit tutar.
const expensiveValue = useMemo(() => computeExpensive(a, b), [a, b]);
const handleClick = useCallback(() => doSomething(id), [id]);
Ancak burada bir uyarı yapmak gerekir: useMemo ve useCallback'i her yerde kullanmak bir performans kazancı sağlamaz; aksine gereksiz karmaşıklık yaratır. Yalnızca ölçülebilir bir darboğaz olduğunda başvurun.
Özel Hook'lar: Mantığı Yeniden Kullanmak
Hooks'un en güçlü yanlarından biri, kendi Hook'larınızı yazabilmenizdir. Özel Hook'lar, bileşenler arasında state mantığını paylaşmanın modern yoludur. Adlandırma kuralı basittir: use önekiyle başlamalıdır.
import { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
Bu Hook'u artık istediğiniz bileşende tek satırla kullanabilirsiniz:
function Layout() {
const width = useWindowWidth();
return <p>Pencere genişliği: {width}px</p>;
}
Özel Hook'lar, kod tekrarını azaltmanın yanı sıra uygulamanızın okunabilirliğini de ciddi ölçüde artırır.
Sık Yapılan Hatalar ve Kaçınma Yolları
Hooks kullanırken geliştiricilerin sıkça düştüğü tuzaklar vardır. Bunları bilmek, saatler süren hata ayıklamadan kurtarır.
- Bağımlılık dizisini eksik bırakmak:
useEffectiçinde kullandığınız her değişken dizide yer almalıdır. Aksi halde "stale closure" hataları ortaya çıkar. - Koşullu Hook çağrıları:
ifbloğu içindeuseStateveyauseEffectçağırmak, React'in Hook sırasını bozar ve uygulamayı çökertir. - useEffect'i her şey için kullanmak: Bazı durumlarda (örneğin türetilmiş veri hesaplamak) efekt yerine doğrudan render içinde hesaplama yapmak daha doğrudur.
- Gereksiz useMemo/useCallback kullanımı: Her fonksiyonu sarmalamak, kodu karmaşıklaştırır ve beklenen faydayı sağlamaz.
- Cleanup fonksiyonunu unutmak: Abonelikler, zamanlayıcılar ve event listener'lar mutlaka temizlenmelidir.
Hooks ile Sınıf Bileşenleri Arasındaki Farklar
Hooks'a geçiş yaparken zihinsel modelinizi de güncellemeniz gerekir. İşte temel farklar:
| Konu | Sınıf Bileşenleri | Hooks |
|---|---|---|
| State | this.state ve this.setState |
useState |
| Yaşam Döngüsü | Birden çok metot | useEffect |
| Mantık Paylaşımı | HOC, render props | Özel Hook'lar |
this Bağlamı |
Gerekli ve kafa karıştırıcı | Yok |
| Kod Organizasyonu | Yaşam döngüsüne göre | İşleve göre |
Hooks, kodunuzu yaşam döngüsü metotlarına göre değil, ilgili mantığa göre organize etmenizi sağlar. Bu, uzun vadede bakımı çok daha kolay bir kod tabanı anlamına gelir.
Sonuç: Hooks'u Doğru Anlamak
React Hooks, yalnızca bir API değişikliği değil; React'te düşünme biçiminizin evrimidir. Fonksiyonel bileşenler, özel Hook'lar ve etkili bağımlılık yönetimiyle çok daha temiz, test edilebilir ve sürdürülebilir uygulamalar yazabilirsiniz.
Unutmayın: Hooks'un gücü, onları ne zaman kullanacağınızı bilmekten gelir. Her problemi Hook ile çözmeye çalışmak yerine, ihtiyacınıza en uygun aracı seçin. Küçük başlayın, özel Hook'lar yazarak mantığınızı soyutlayın ve React'in sunduğu bu modern yaklaşımın tadını çıkarın.
React ekosistemi gelişmeye devam ediyor; ancak Hooks, önümüzdeki yıllarda da modern React geliştirmenin temel taşı olmayı sürdürecek gibi görünüyor.