Ön Hazırlık ve Gereksinimler
Projeye başlamadan önce bilgisayarınızda Node.js yüklü olduğundan emin olun. React projeleri için güncel bir geliştirme ortamı (Vite veya Next.js) kullanmanızı öneriyoruz. 2026 yılı itibarıyla React 19 ve üzeri sürümlerle çalışmak, performans ve geliştirici deneyimi açısından en verimli yoldur.
- Node.js: LTS sürümü (v20 veya üzeri).
- Paket Yöneticisi: npm, yarn veya pnpm.
- Editör: VS Code ve React eklentileri.
Yeni bir proje oluşturmak için terminalinizde şu komutu çalıştırabilirsiniz:
npm create vite@latest sayaç-projesi -- --template react
cd sayaç-projesi
npm install
npm run dev
Adım 1: Temel Sayaç Mantığını Anlamak
Özel bir kanca oluşturmadan önce, sayacın temel mantığını useState kancası ile nasıl kurduğumuzu hatırlayalım. Bu, özel kancanın hangi karmaşıklığı soyutladığını anlamamıza yardımcı olacaktır.
import { useState } from 'react';
function BasitSayac() {
const [sayac, setSayac] = useState(0);
return (
Sayaç: {sayac}
setSayac(sayac + 1)}>Artır
);
}
Yukarıdaki örnekte, durum yönetimi bileşenin içinde tanımlanmıştır. Eğer bu sayacı üç farklı sayfada kullanmak isterseniz, aynı kod bloğunu kopyalayıp yapıştırmanız gerekir; bu da bakım maliyetini artırır.
Adım 2: Özel Kanca (useCounter) Oluşturma
Özel kancalar, içerisinde React kancalarını (useState, useEffect vb.) barındıran JavaScript fonksiyonlarıdır. İsimleri mutlaka use ön eki ile başlamalıdır. Şimdi, sayaç mantığını dışarı çıkaralım.
import { useState } from 'react';
export function useCounter(baslangicDegeri = 0) {
const [sayac, setSayac] = useState(baslangicDegeri);
const artir = () => setSayac(s => s + 1);
const azalt = () => setSayac(s => s - 1);
const sifirla = () => setSayac(baslangicDegeri);
return { sayac, artir, azalt, sifirla };
}
Bu fonksiyon, bileşenin ihtiyaç duyduğu tüm metotları ve durumu bir nesne olarak döndürür. Böylece bileşen, sayacın nasıl çalıştığıyla değil, sadece sonuçla ilgilenir.
Adım 3: Özel Kancayı Bileşende Kullanma
Oluşturduğumuz useCounter kancasını artık herhangi bir bileşende kolayca çağırabiliriz. Bu, kodun temiz ve okunabilir kalmasını sağlar.
import { useCounter } from './hooks/useCounter';
function SayaçBileseni() {
const { sayac, artir, azalt, sifirla } = useCounter(10);
return (
Güncel Değer: {sayac}
Artır
Azalt
Sıfırla
);
}
Gördüğünüz gibi, bileşen artık çok daha temiz. Mantık kancanın içinde gizlendiği için bileşen sadece arayüzü çizmeye odaklanıyor.
Adım 4: Kanca Mantığını Geliştirme ve Sınırlandırma
Gerçek dünya uygulamalarında sayacın belirli sınırları olması gerekebilir (örneğin 0'ın altına düşmemesi). Kancamızı bu mantığı da içerecek şekilde güncelleyelim.
export function useCounter(baslangicDegeri = 0, min = 0, max = 100) {
const [sayac, setSayac] = useState(baslangicDegeri);
const artir = () => setSayac(s => (s < max ? s + 1 : s));
const azalt = () => setSayac(s => (s > min ? s - 1 : s));
return { sayac, artir, azalt };
}
Bu yaklaşım, bileşenlerinizdeki "if" bloklarını azaltır ve iş mantığını merkezi bir noktada toplar. Test edilebilirliği artıran en önemli adım budur.
Adım 5: Karşılaştırma ve Avantajlar
Özel kanca kullanmanın geleneksel yöntemlere göre avantajlarını aşağıdaki tabloda özetledik:
| Özellik | useState (Bileşen İçi) | Özel Kanca (useCounter) |
|---|---|---|
| Yeniden Kullanılabilirlik | Düşük | Yüksek |
| Kod Karmaşıklığı | Yüksek | Düşük |
| Test Edilebilirlik | Zor | Kolay |
| Bakım | Zamanla zorlaşır | Merkezi ve kolay |
Adım 6: Hata Ayıklama ve Kritik Uyarılar
Güvenlik ve Performans Uyarısı: React kancalarını asla döngüler, koşullu ifadeler veya iç içe fonksiyonlar içerisinde çağırmayın. Kancalar, her zaman bileşenin en üst seviyesinde çağrılmalıdır. Aksi takdirde React'in içsel durum takibi bozulur ve uygulamanız beklenmedik hatalar verir.
Yaygın bir hata, kancayı bir "event handler" içerisinde çağırmaktır. Bu, React'in "Hooks can only be called inside the body of a function component" hatasını tetikler.
// YANLIŞ KULLANIM
function HatalıBileşen() {
const handleClick = () => {
const { sayac } = useCounter(); // HATA!
};
return Tıkla;
}
Sıkça Sorulan Sorular
Özel kancalar neden "use" ile başlamalı?
React, kancaların kurallara uygun kullanılıp kullanılmadığını kontrol etmek için "use" ön ekini kullanır. Eğer kendi fonksiyonunuza bu ön eki koymazsanız, React içerisindeki diğer kancaları (useState, useEffect gibi) çağıramazsınız.
Birden fazla bileşende aynı kancayı kullanırsam durumlar birbirini etkiler mi?
Hayır. Her kanca çağrısı, o bileşene özel, izole bir durum (state) oluşturur. Bir bileşendeki sayaç artarken diğeri bundan etkilenmez.
useCounter kancasını dışarıdan parametre ile yönetebilir miyim?
Evet, fonksiyonunuza parametre göndererek başlangıç değerini veya sınırları dinamik olarak belirleyebilirsiniz, tıpkı yukarıdaki örneklerde yaptığımız gibi.
Özel kancalar sadece durum (state) için mi kullanılır?
Hayır, özel kancalar API çağrıları yapmak, tarayıcı olaylarını dinlemek (scroll, resize) veya yerel depolama (localStorage) ile etkileşime geçmek gibi her türlü yan etki mantığı için kullanılabilir.
Performans kaybı yaşanır mı?
Hayır, özel kancalar sadece kodun düzenlenmesini sağlayan bir soyutlama katmanıdır. Çalışma zamanında (runtime) ekstra bir performans maliyeti oluşturmazlar.
İleri Seviye İpuçları: useCounter'ı localStorage ile Kalıcı Hale Getirme
Özel kancaların gücünü tam anlamıyla kullanmak için, onları sadece bellek içi (in-memory) değişkenler olarak değil, tarayıcı depolama alanlarıyla senkronize çalışan yapılar olarak kurgulayabilirsiniz. Sayacın sayfa yenilendiğinde sıfırlanmasını istemiyorsanız, useEffect kancasını useCounter içerisine entegre ederek veriyi kalıcı hale getirebilirsiniz.
import { useState, useEffect } from 'react';
function usePersistentCounter(initialValue, key) {
const [count, setCount] = useState(() => {
const saved = localStorage.getItem(key);
return saved !== null ? JSON.parse(saved) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(count));
}, [count, key]);
const increment = () => setCount(c => c + 1);
const decrement = () => setCount(c => c - 1);
const reset = () => setCount(initialValue);
return { count, increment, decrement, reset };
}
Bu yaklaşım, kullanıcı deneyimini iyileştirirken uygulamanızın durum yönetimini daha profesyonel bir seviyeye taşır. key parametresi sayesinde, aynı kancayı farklı sayaçlar için çakışma yaşamadan kullanabilirsiniz.
Özel Kancalar İçin Birim Testi (Unit Testing) Yazma
Özel kancalar mantıksal birimler olduğu için, onları bileşenlerden bağımsız olarak test etmek mümkündür. @testing-library/react-hooks kütüphanesi, kancalarınızı izole bir şekilde test etmenize olanak tanır. İşte basit bir test senaryosu örneği:
import { renderHook, act } from '@testing-library/react-hooks';
import { useCounter } from './useCounter';
test('sayacı artırmalıdır', () => {
const { result } = renderHook(() => useCounter(0));
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
test('sayacı sıfırlamalıdır', () => {
const { result } = renderHook(() => useCounter(10));
act(() => {
result.current.reset();
});
expect(result.current.count).toBe(10);
});
Test süreçleri, kancalarınızın karmaşıklaştığı durumlarda beklenmedik yan etkilerin oluşmasını engeller. Özellikle useEffect içeren kancalarda, zaman uyumsuz (asynchronous) güncellemeleri test etmek için waitForNextUpdate gibi yardımcı fonksiyonları kullanmanız önerilir.
Performans Optimizasyonu: useMemo ve useCallback
Kancalarınızın döndürdüğü fonksiyonlar, her render işleminde yeniden oluşturulabilir. Eğer bu kancayı büyük bir bileşen ağacında kullanıyorsanız, useCallback kullanarak fonksiyon referanslarını sabitlemek, alt bileşenlerin gereksiz yere tekrar render edilmesini engeller.
import { useState, useCallback } from 'react';
export function useOptimizedCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = useCallback(() => setCount(c => c + 1), []);
const decrement = useCallback(() => setCount(c => c - 1), []);
return { count, increment, decrement };
}
Bu küçük dokunuş, React'in "referans eşitliği" (referential equality) prensibi sayesinde React.memo ile sarmalanmış alt bileşenlerinizin performansını doğrudan korur.
Sonuç
React ile özel kanca kullanarak sayaç yapmak, sadece temiz kod yazmanın ötesinde, bileşenlerinizin modülerliğini artıran temel bir beceridir. useCounter örneği üzerinden öğrendiğimiz bu mantığı, form yönetimi, API entegrasyonları veya kimlik doğrulama süreçleri gibi çok daha karmaşık yapılara uygulayabilirsiniz. Bir sonraki adım olarak, bu kancayı localStorage ile entegre ederek sayacın tarayıcı yenilense bile değerini korumasını sağlayabilirsiniz.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim (production) ortamında kullanırken verilerinizi doğrulamayı, XSS saldırılarına karşı girdi temizliği yapmayı ve uygulamanızın güvenlik açıklarını düzenli olarak taramayı unutmayın.


Yorumlar (0)
Yorum Yaz