React Hooks — nedir, temel hook’lar ve kullanım kuralları

Yazar: IT Sectr Yayınlanma: 2026-07-04 Okuma süresi: 10 dk

React Hooks, sınıf yazmadan işlevsel bileşenlerde durum, efektler, bağlam ve diğer React özelliklerini kullanmanıza olanak tanıyan işlevlerdir. React 16.8’de tanıtılan hook’lar, HOC ve render props gibi karmaşık kalıpların yerini alarak geliştirme yaklaşımını kökten değiştirdi. React, 2024’e göre, tüm bileşen yönetimi senaryolarını kapsayan 15 yerleşik hook bulunmaktadır.

Önemli Noktalar

  • Hook’lar — extends Component olmadan işlevsel bileşenlere React özelliklerini bağlamak için işlevler.
  • useState — durum yönetimi için temel hook, bir değer ve bir setter döndürür.
  • useEffect — yan etkiler için: API istekleri, abonelikler, zamanlayıcılar, DOM manipülasyonları.
  • useContext — Consumer sarmalayıcıları ve static contextType olmadan React bağlamına erişmek için.
  • Hook kuralları — yalnızca en üst düzeyde ve yalnızca işlevsel bileşenler veya özel hook’lar içinde çağrın.

React Hook’ları Nedir?

React Hooks, sınıf oluşturmadan çerçevenin iç mekanizmalarına “bağlanmanıza” olanak tanıyan, React’e yerleşik işlevler kümesidir. React 16.8’den önce, işlevsel bileşenler yalnızca props alabilir ve JSX döndürebilirdi — herhangi bir karmaşık mantık için bir sınıf bileşeni gerekiyordu.

Sınıf bileşenlerinin sorunu ilgili mantığın bölünmesidir. Aynı varlıkla ilgili kod (örneğin bir WebSocket aboneliği) zorla componentDidMount, componentDidUpdate ve componentWillUnmount arasında bölünüyordu. Hook’lar bunu çözer: tüm mantık tek bir useEffect’te gruplandırılır.

İkinci sorun mantığın yeniden kullanımıdır. Sınıf bileşenleri arasında durum mantığını yeniden kullanmak için HOC (Üst Düzey Bileşenler) veya render props uygulamak gerekiyordu — her iki kalıp da bileşen ağacında ekstra iç içelik yaratıyordu. Özel hook’lar bunu iç içelik olmadan çözer.

useState — Durum Yönetimi

useState en temel hook’tur. Bir başlangıç değeri alır ve bir demet döndürür: geçerli değer ve onu güncellemek için bir işlev. Sınıflardaki this.setState’in aksine, useState nesneleri birleştirmez — yeni durum, belirli bir useState çağrısı için önceki durumu tamamen değiştirir.

js
import React, { useState } from 'react';

function Form() {
  const [text, setText] = useState('');
  const [submitting, setSubmitting] = useState(false);

  async function handleSubmit() {
    setSubmitting(true);
    await fetch('/api/submit', {
      method: 'POST',
      body: JSON.stringify({ text })
    });
    setSubmitting(false);
  }

  return (
    <div>
      <input
        value={text}
        onChange={e => setText(e.target.value)}
      />
      <button onClick={handleSubmit}
        disabled={submitting}>
        {submitting ? 'Saving...' : 'Submit'}
      </button>
    </div>
  );
}

setState’in İşlevsel Biçimi

useState setter’ı, önceki değeri alan ve yeni bir değer döndüren bir işlevi kabul edebilir. İşlevsel biçim, yeni durum öncekinden hesaplandığında ve toplu setState çağrıları mümkün olduğunda zorunludur — her çağrı geçerli önceki değeri alacaktır.

useEffect — Yan Etkiler ve Yaşam Döngüsü

useEffect, işlevsel bileşenlerde yan etkiler gerçekleştirmek için bir hook’tur. İki argüman alır: bir efekt işlevi ve bir bağımlılık dizisi. React, efekti her render’dan sonra çalıştırır, ancak bağımlılıklar belirtildiğinde — yalnızca bunlardan biri değiştiğinde.

Boş bir bağımlılık dizisi [], efektin ilk render’dan sonra bir kez çalıştığı anlamına gelir (componentDidMount’a benzer). Efektten bir işlev döndürmek, unmount sırasında (componentWillUnmount’a benzer) ve efekti yeniden çalıştırmadan önce çalışan bir temizleme işlevidir.

js
import React, { useState, useEffect } from 'react';

function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = new WebSocket(`wss://chat/${roomId}`);

    socket.onmessage = (event) => {
      setMessages(prev => [...prev, JSON.parse(event.data)]);
    };

    // Temizlik - soketi kapat
    return () => socket.close();
  }, [roomId]);

  return <ul>
    {messages.map((msg, i) =>
      <li key={i}>{msg.text}</li>
    )}
  </ul>;
}

useEffect bağımlılıkları, efekt ile dış dünya arasındaki tek bağlantıdır. Efekt, props veya durumdan bir değişken kullanıyorsa, bağımlılık dizisinde olmalıdır. Bu kuralı görmezden gelmek, eski kapanımlarla (stale closure) ilgili hataların kaynağıdır.

useContext — Bağlama Erişim

useContext, bağlam değerlerini okumak için bir hook’tur. React.createContext tarafından oluşturulan bir bağlam nesnesini alır ve geçerli değeri döndürür. Bağlam değişirse, bileşen otomatik olarak yeni değerle yeniden render edilir.

useContext’ten önce, işlevsel bileşenlerde bağlama erişmek için Context.Consumer ile sarmalamak gerekiyordu, bu da iç içelik yaratıyordu. useContext, Consumer’ı tamamen ortadan kaldırır — işlevsel bileşende herhangi bir yerde hook’u çağırmanız yeterlidir.

js
import React, { createContext, useContext } from 'react';

const ThemeContext = createContext('açık');

function ThemedButton() {
  const theme = useContext(ThemeContext);

  return <button
    className={`btn btn-${theme}`}
  >
    {theme === 'dark' ? 'moon' : '☀️'}
  </button>;
}

useContext, Redux veya küresel durumun yerine geçmez. React, bağlamı nadiren değişen değerler için kullanmayı önerir — tema, yerel ayar, kimlik doğrulama durumu. Sık güncellenen veriler için, her yeniden render tüm bağlam tüketicilerini yeniden hesaplar ve bu da performansı düşürebilir.

useReducer — Karmaşık Durum Mantığı

useReducer, karmaşık güncelleme mantığına sahip durumlar için useState’e bir alternatiftir. Bir indirgeyici işlevi ve başlangıç durumunu alır, geçerli durumu ve bir dispatch işlevini döndürür. İndirgeyici, geçerli durumu ve bir eylemi alır, yeni bir durum döndürür — yan etkileri olmayan saf bir işlev.

useReducer, birden çok eylem (set, reset, increment, addItem) tek bir durumu yönettiğinde özellikle kullanışlıdır. Farklı setter’larla birden çok useState yerine — net eylem türlerine sahip tek bir indirgeyici. Bu, mantığı öngörülebilir ve kolayca test edilebilir hale getirir.

js
import React, { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + 1 };
    case 'setStep':
      return { ...state, step: action.step };
    case 'reset':
      return { count: 0, step: 1 };
    default:
      throw new Error('Unknown action: ' + action.type);
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, {
    count: 0,
    step: 1
  });

  return (
    <>
      <p>Count: {state.count}</p>
      <button
        onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button
        onClick={() => dispatch({ type: 'reset' })}>Reset</button>
    </>
  );
}

useRef, useMemo, useCallback — Optimizasyon

useRef, render’lar arasında kalıcı olan değiştirilebilir bir nesne oluşturur. current’ı değiştirmek yeniden render’ı tetiklemez. Ana kullanım alanları, DOM öğelerine erişmek ve değiştirilebilir değerleri (zamanlayıcılar, önceki değerler, kütüphane örnekleri) depolamaktır.

useMemo bir işlevin sonucunu belleğe alır. Değeri yalnızca bir bağımlılık değiştiğinde yeniden hesaplar. Pahalı hesaplamalar için kullanın — büyük dizileri filtreleme, sıralama, veri biçimlendirme. useCallback, işlevleri belleğe almak için useMemo’nun özel bir durumudur.

js
import React, { useRef, useMemo, useCallback } from 'react';

function SearchPage({ items, query, onItemSelect }) {
  const inputRef = useRef(null);

  // Mount’ta otomatik odak
  useEffect(() => {
    inputRef.current?.focus();
  }, []);

  // Filtrelenmiş sonucu belleğe al
  const filtered = useMemo(() => {
    return items.filter(item =>
      item.name.toLowerCase()
        .includes(query.toLowerCase())
    );
  }, [items, query]);

  // Geri aramayı belleğe al
  const handleSelect = useCallback((id) => {
    onItemSelect(id);
  }, [onItemSelect]);

  return (
    <div>
      <input ref={inputRef}
        value={query}
        onChange={e => setQuery(e.target.value)}
      />
      <ul>
        {filtered.map(item =>
          <li key={item.id}>
            <button
              onClick={() => handleSelect(item.id)}>
              {item.name}
            </button>
          </li>
        )}
      </ul>
    </div>
  );
}

Önemli bir kural: useRef, useMemo ve useCallback optimizasyon araçlarıdır, zorunlu yapılar değil. Her şeyi useMemo ile sarmayın — önce performansı ölçün. Erken optimizasyon kodu karmaşıklaştırır. React bileşenleri hızlı bir şekilde render eder; useMemo yalnızca hesaplamalar gerçekten pahalı olduğunda (O(n²) ve üzeri) gereklidir.

Hook Kuralları ve Yaygın Hatalar

React, hook’lar için iki katı kural getirmiştir. Birincisi: hook’ları yalnızca en üst düzeyde çağırın — koşullar, döngüler veya iç içe işlevler içinde değil. İkincisi: hook’ları yalnızca React işlevsel bileşenlerinden veya özel hook’lardan çağırın. ESLint eklentisi eslint-plugin-react-hooks her iki kuralı da otomatik olarak denetler.

En yaygın hata hook çağrı sırasını ihlal etmektir. React, render’lar arasındaki hook çağrı sırasına güvenir. Bir hook bir koşul içindeyse ve bir render’da çalışmazsa, sonraki tüm hook’lar kayar ve hatalara neden olur.

HataNe OlurÇözüm
Koşulda hookHook sırası bozulurKoşul mantığını hook içine taşıyın
Stale closureEfekt eski değeri kullanırTüm bağımlılıkları diziye ekleyin
Sonsuz döngüBağımlılığı olmayan useEffect durumu değiştirirBağımlılıkları belirtin veya useReducer kullanın
Render’da ref değişikliğiİşlev gövdesinde yan etkiMutasyonları useEffect’e taşıyın

İkinci yaygın hata, useEffect’teki stale closure’dır. Efekt, bağımlılıklarda belirtilmeyen bir değişken kullanırsa, efekt kapanım oluşturma anındaki değerini “yakalar”. Çözüm, kullanılan tüm değişkenleri her zaman bağımlılık dizisine dahil etmektir. Çok fazla bağımlılık varsa, efekti birden çok parçaya bölmeyi düşünün.

Sıkça Sorulan Sorular

Hook’lar neden koşullar içinde çağrılamaz?

React, render’lar arasındaki hook çağrı sırasına güvenir. Bir hook bir koşul içinde çağrılır ve bir render’da çalışmazsa, sonraki tüm hook’lar kayar — durumları karışır. ESLint kuralı hooks/exhaustive-deps bu konuda uyarır.

useEffect ve useLayoutEffect arasındaki fark nedir?

useLayoutEffect eş zamanlıdır ve tarayıcı değişiklikleri çizmeden önce çalışır. useEffect eş zamansızdır — çizimden sonra. useLayoutEffect’i yalnızca kullanıcı değişiklikleri görmeden önce DOM’u ölçmeniz veya değiştirmeniz gerektiğinde kullanın (popover konumu, kaydırma geri yükleme).

Unmount sırasında fetch isteği nasıl iptal edilir?

useEffect içinde AbortController kullanın. Bir controller oluşturun, signal’ı fetch’e iletin ve temizleme işlevinde controller.abort() çağrın. Eski tarayıcılar için bir cancelled bayrağı kullanın: return () => { cancelled = true; } setState’ten önce bir kontrol ile.

Özel hook nedir ve ne zaman oluşturulur?

Özel hook, yerleşik hook’ları kullanan, use önekli bir JavaScript işlevidir. Aynı hook mantığı iki veya daha fazla bileşende tekrarlandığında oluşturun. Örnekler: useDebounce, useLocalStorage, useMediaQuery. Özel hook’lar HOC ve render props’ın yerini alır.

Strict Mode’da useEffect neden iki kez çalışır?

Strict Mode’da React, geliştirme ortamında temizlenmemiş efektlerle ilgili hataları bulmak için bileşeni kasıtlı olarak iki kez mount ve unmount eder. Temizleme doğru yazılmışsa, çift çağrı soruna neden olmaz. Bu, üretim modunda gerçekleşmez.

Özet

  • React Hooks — sınıfların yerini alarak işlevsel bileşenlerde durum, efekt ve bağlam kullanmak için işlevler.
  • useState — güvenli güncellemeler için işlevsel setter ile yerel durum için temel hook.
  • useEffect — bağımlılık dizisi ve temizleme işlevi ile yan etkiler için evrensel hook.
  • useContext — Consumer sarmalayıcıları ve ekstra iç içelik olmadan React bağlamına doğrudan erişim.
  • useReducer — tek bir bileşen içinde Redux’a alternatif olarak eylem türleriyle karmaşık durum mantığı için.
  • useRef, useMemo, useCallback — optimizasyon araçları: DOM referansları, değer ve geri arama belleğe alma.
  • Üst düzey kuralı — hook’ları koşullar, döngüler ve iç içe işlevler dışında çağırma konusunda katı kısıtlama.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun