Custom Hooks

Custom hook nedir, use öneki ve isimlendirme kuralı, aynı hook'u birden fazla kez kullanmak, ve bir useFetch örneği -- basit örneklerle.

Orta 10 dk
EN

Custom Hooks

Bu kategoride useState, useEffect, useRef, useMemo, useCallback gibi React'in hazır hook'larını gördük. Bu son ders, kendi hook'unu yazmayı -- bir custom hook -- anlatıyor.

Custom Hook Nedir?

Birden fazla component'te aynı state+effect mantığını tekrar tekrar yazdığını fark edersen, bu mantığı bir custom hook'a çıkarabilirsin. Custom hook, React'in kendi hook'larını (useState, useEffect gibi) içeride kullanan, senin yazdığın normal bir fonksiyondur.

use Öneki ve İsimlendirme Kuralı

Bir fonksiyonun custom hook sayılması için tek şart, isminin use ile başlaması:

import { useState } from "react";

// Özel bir hook, "use" ile başlayan NORMAL bir JavaScript fonksiyonudur --
// içinde React'in kendi hook'larını (useState, useEffect gibi) çağırabilir.
function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);

  function increment() {
    setCount((prev) => prev + 1);
  }

  function decrement() {
    setCount((prev) => prev - 1);
  }

  return { count, increment, decrement };
}

function CustomHookNamingExample() {
  const { count, increment, decrement } = useCounter(0);

  return (
    <div>
      <p>Sayaç: {count}</p>
      <button onClick={increment}>+1</button>
      <button onClick={decrement}>-1</button>
    </div>
  );
}

useCounter, içinde useState çağıran, senin yazdığın bir fonksiyon -- React'in kendi hook'larından biri değil. use öneki, hem React'e (Rules of Hooks kontrolleri için) hem de seni okuyan diğer geliştiricilere "bu bir hook, içinde başka hook'lar çağırabilir" sinyalini veriyor.

Aynı Hook'u Birden Fazla Kez Kullanmak

Bir custom hook'u aynı component içinde birden fazla kez çağırabilirsin -- her çağrı kendi BAĞIMSIZ state'ine sahip olur:

import { useState } from "react";

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  return {
    count,
    increment: () => setCount((prev) => prev + 1),
  };
}

function ReusingCustomHookExample() {
  // Aynı hook'u iki kez çağırıyoruz -- her çağrı kendi BAĞIMSIZ state'ine sahip.
  const apples = useCounter(0);
  const oranges = useCounter(10);

  return (
    <div>
      <p>Elma: {apples.count}</p>
      <button onClick={apples.increment}>Elma Ekle</button>

      <p>Portakal: {oranges.count}</p>
      <button onClick={oranges.increment}>Portakal Ekle</button>
    </div>
  );
}

apples ve oranges, aynı useCounter hook'unu kullanıyor, ama birbirinden tamamen bağımsız iki ayrı state. Bu, custom hook'ların gücü: state'i YÖNETME MANTIĞINI yeniden kullanıyorsun, state'in KENDİSİNİ değil.

Örnek: useFetch ile Veri Çekme

Gerçek projelerde sık görülen bir custom hook örneği, veri çekme mantığını sarmalayan useFetch:

import { useState, useEffect } from "react";

// useEffect + useState'i tekrar tekrar yazmak yerine, "veri çekme" mantığını
// yeniden kullanılabilir bir custom hook'a çıkarıyoruz. (Basitleştirilmiş
// bir örnek -- hata yönetimi ve yarış durumları gibi konular "API & Data
// Fetching" kategorisinde daha detaylı işlenecek.)
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then((response) => response.json())
      .then((json) => {
        setData(json);
        setLoading(false);
      });
  }, [url]);

  return { data, loading };
}

function UseFetchExample() {
  const { data, loading } = useFetch("https://api.example.com/users");

  if (loading) {
    return <p>Yükleniyor...</p>;
  }

  return <p>{data.length} kullanıcı bulundu.</p>;
}

useFetch, useState (veri ve yükleniyor durumu için) ile useEffecti (veriyi çekmek için) bir araya getiriyor ve bunları her component'te tekrar yazmak yerine tek bir yerde topluyor. Bu, basitleştirilmiş bir örnek -- hata yönetimi gibi konuları ileride "API & Data Fetching" kategorisinde daha detaylı göreceğiz.

Özet ve Terimler Sözlüğü

Custom hook, use ile başlayan, içinde React'in kendi hook'larını kullanabilen, senin yazdığın normal bir fonksiyondur. Tekrar eden state+effect mantığını bir custom hook'a çıkarmak, aynı mantığı birden fazla component'te (ya da aynı component içinde birden fazla kez) bağımsız state'lerle yeniden kullanmanı sağlar.

Terimler Sözlüğü

Custom Hookuse ile başlayan, içinde React'in kendi hook'larını kullanabilen, geliştiricinin kendi yazdığı fonksiyon.

Kod Yeniden Kullanımı (Code Reuse) — Aynı mantığı birden fazla yerde tekrar yazmak yerine, tek bir yerden (burada bir custom hook'tan) paylaşma.

Pratik Proje

Bu kategoride (What Are Hooks?, useEffect, useRef, useMemo & useCallback, Custom Hooks) öğrendiğimiz kavramları bir arada kullanan, gerçek ve çalıştırılabilir bir örnek proje var: Hooks Demo -- tur (lap) kaydı yapabilen basit bir kronometre uygulaması.

Proje; bir custom hook (useStopwatch) içinde useEffect+cleanup ile setInterval yönetimini, useRef ile hem bir DOM elementine erişip otomatik kaydırma yapmayı hem de render'ı tetiklemeyen kalıcı bir sayaç tutmayı, useMemo ile en iyi turu yalnızca gerektiğinde yeniden hesaplamayı, ve useCallback ile bir fonksiyon referansını sabit tutmayı bir arada gösteriyor. Bilgisayarına indirip çalıştırabilir, kodunu satır satır inceleyebilirsin:

git clone https://github.com/cdurgun/react-course-projects.git
cd react-course-projects
npm install
cd projects/hooks
npm run dev

react-course-projects deposu npm workspaces kullanır -- npm install yalnızca bir kez, depo kökünde çalıştırılır ve tüm proje klasörleri ortak bağımlılıkları paylaşır (her klasörde ayrı bir node_modules oluşmaz). Kök dizinde npm install'ı daha önce çalıştırdıysan, doğrudan cd react-course-projects/projects/hooks yapıp npm run dev demen yeterli.