useCallback, bağımlılıkları değişene kadar oluşturmalar arasında değişmeyen bir işlevin belleğe alınmış sürümünü döndüren bir React hook'udur. Bir bileşen içindeki normal işlev bildiriminin (her oluşturmada yeni bir işlev oluşturur) aksine, useCallback işlev referansını stabilize ederek React.memo ile optimize edilmiş alt bileşenlerin gereksiz yeniden oluşturulmasını önler. React Documentation (2025)'a göre, useCallback yalnızca React.memo veya kararlı bir referansa bağlı hook'larla birlikte kullanıldığında faydalıdır.
Önemli Noktalar
useCallback, React 16.8'de eklenen ve bir işlevi belleğe alan bir hook'tur: bağımlılıklar değişene kadar aynı referansı döndürür. useCallback olmadan, bir bileşen içindeki her işlev bildirimi her oluşturmada yeni bir işlev nesnesi oluşturur. İlkeller için bu fark edilmez, ancak bu callback'leri React.memo ile optimize edilmiş alt bileşenlere iletirken, her yeni referans alt bileşenin yeniden oluşturulmasına neden olur.
Sözdizimsel olarak, useCallback bir işlev için useMemo'ya eşdeğerdir: useCallback(fn, deps), useMemo(() => fn, deps) için kısa yoldur. React, belleğe alınmış işlevi fiber düğümünün dahili deposunda tutar ve her oluşturmada bağımlılıkları karşılaştırır. Bağımlılıklar değişmemişse (her öğe için Object.is), önceki işlev döndürülür.
React Documentation — useCallback (2025)'a göre, her işlevi useCallback ile sarmamalısınız. Hook'un kendi maliyeti vardır: hook'u çağırma, bağımlılıkları karşılaştırma ve bağımlılık dizisi için bellek ayırma. Bir bileşen basitse ve React.memo ile derin ağaçları yoksa, useCallback yalnızca uygulamayı yavaşlatır. Optimizasyon ölçülebilir olmalı, sezgisel değil.
import { useCallback } from 'react';
function Parent() {
const [count, setCount] = useState(0);
// Kararlı referans — deps değişene kadar aynı işlev
const handleClick = useCallback(() => {
setCount(prev => prev + 1);
}, []);
return <Child onClick={handleClick} />;
}
useCallback içindeki bellekleme, işlev çağrısının sonucunu önbelleğe almaya dayanır. React, ilk oluşturma sırasında oluşturulan kapanımı (closure) korur ve bağımlılıklar değişmediği sürece sonraki oluşturmalarda onu döndürür. Fiber düğümü içinde, her useCallback çağrısı, önceki bağımlılıkların ve belleğe alınmış değerin depolandığı hook'ların bağlantılı listesinde bir düğüm oluşturur.
Bağımlılık karşılaştırması kesinlikle Object.is aracılığıyla yapılır — nesnelerin veya dizilerin derinlemesine kontrolü olmadan yüzeysel bir karşılaştırma. Bir bağımlılık bir nesne veya dizi ise, her oluşturmada yeni bir referans değişiklik olarak kabul edilir. Bu nedenle, bağımlılık dizisi ilkel değerler veya kararlı referanslar (örneğin, useRef veya useMemo'dan) içermelidir.
React Core Team — Optimization Guide (2024)'e göre, belleklemenin maliyeti üç bileşen içerir: her oluşturmada bağımlılık dizisi ayırma, Object.is aracılığıyla öğeleri yineleme ve karşılaştırma ve yeniden oluşturma sırasında potansiyel çöp toplama yükü. Yüzlerce useCallback sarmalayıcısı olan bir bileşen için bu fark edilebilir hale gelebilir — bu nedenle hook kullanımında seçicilik çok önemlidir.
| Senaryo | useCallback Olmadan | useCallback ile |
|---|---|---|
| İşlev oluşturma | Her oluşturmada yeni | Kararlı deps ile aynı |
| React.memo'ya aktarma | Alt yeniden oluşturulur | Alt yeniden oluşturulmaz |
| useEffect dizisinde | Efekt yeniden başlar | Efekt kararlı |
| Yük | Minimum | Bağımlılık karşılaştırması + bellek |
useCallback'in otomatik olarak performansı artırdığına dair yaygın bir yanlış kanı vardır. Gerçekte, tek başına (React.memo olmadan), useCallback bağımlılık karşılaştırma maliyeti nedeniyle uygulamayı biraz yavaşlatır. Hook yalnızca üç senaryoda gerçek fayda sağlar: React.memo bileşenlerinin yeniden oluşturulmasını önleme, useEffect'te callback'leri kararlı hale getirme ve referans eşitliğine bağlı özel hook'lara callback aktarma.
Kural basittir: React DevTools Profiler ile bir performans sorunu tespit edene kadar useCallback kullanmayın. React ekibi, erken optimizasyonun tüm kötülüklerin kaynağı olduğunu defalarca vurgulamıştır. Önce bellekleme olmadan temiz kod yazın, ölçün, profil oluşturucuda darboğazı bulun ve ancak o zaman gerçekten gerekli yerlere useCallback ekleyin.
// Ölçülebilir optimizasyon: Child, React.memo ile sarılmış
const Child = React.memo(({ onClick }) => {
console.log('Child yeniden oluşturuldu');
return <button onClick={onClick}>Click</button>;
});
function Parent() {
const handleClick = useCallback(() => {
console.log('tıklandı');
}, []);
return <Child onClick={handleClick} />;
}
Dan Abramov — Before You memo() (2024)'e göre, açık kaynak projelerde useCallback kullanımının %90'ından fazlası gereksizdir. Geliştiriciler, etkiyi ölçmeden "her ihtimale karşı" her işlevi sararlar. Alternatif: alt bileşen ağırsa ve yeniden oluşturulması pahalıysa — React.memo + useCallback haklıdır. Alt bileşen hafifse — yeniden oluşturma, bağımlılık karşılaştırmasından daha ucuzdur.
İlk senaryo React.memo'dur. Bir alt bileşen React.memo ile sarılmışsa ve bir prop olarak callback işlevi alıyorsa, useCallback olmadan alt bileşen, kendi verileri değişmemiş olsa bile her üst oluşturmada yeniden oluşturulur. useCallback referansı kararlı hale getirir ve React.memo'nun yeniden oluşturmayı doğru şekilde atlamasını sağlar.
İkinci senaryo, bağımlılıklarda callback ile useEffect'tir. Bir işlev useEffect bağımlılık dizisine aktarılırsa, her yeni referans efekti yeniden başlatır. useCallback, referansın kararlı olmasını ve efektin yalnızca gerçek veriler değiştiğinde çalışmasını sağlar, her oluşturmada değil. Bu, özellikle abonelikler ve istekler için önemlidir.
// Kararlı useEffect bağımlılığı için useCallback
const fetchData = useCallback(async (id) => {
const res = await fetch(`/api/${id}`);
setData(res.data);
}, []); // kararlı referans, asla yeniden oluşturulmaz
useEffect(() => {
fetchData(props.id);
}, [props.id, fetchData]); // efekt yalnızca props.id değiştiğinde çalışır
useCallback ve useMemo arasındaki temel fark, her birinin neyi belleğe aldığıdır. useCallback bir işlevi belleğe alır: useCallback(fn, deps), fn'i (aynısı veya önceki sürümü) döndürür. useMemo bir işlev çağrısının sonucunu belleğe alır: useMemo(() => computeExpensive(a, b), [a, b]) hesaplanan değeri döndürür, bir işlevi değil.
Teknik olarak, useCallback, useMemo üzerinde sözdizimsel şekerdir: useCallback(fn, deps), useMemo(() => fn, deps) ile eşdeğerdir. Bu sözdizimi yalnızca okunabilirlik için vardır — geliştiricinin bir değer değil, bir işlevin belleğe alındığını açıkça görmesi için. useCallback ve bir işlevle useMemo arasında performans farkı yoktur — aynı kodu üretirler.
| Hook | Belleğe alır | Sözdizimi | Kullanım |
|---|---|---|---|
| useCallback | İşlev (referans) | useCallback(fn, deps) | Alt bileşenler için callback'ler |
| useMemo | Hesaplama sonucu | useMemo(() => value, deps) | Pahalı hesaplamalar, nesne bellekleme |
// Bunlar eşdeğerdir:
const handleClick = useCallback(() => doSomething(a, b), [a, b]);
const handleClick = useMemo(() => () => doSomething(a, b), [a, b]);
En yaygın hata, alt bileşenlerde React.memo olmadan tüm işlevleri useCallback ile anlamsızca sarmaktır. Bir alt bileşen React.memo ile sarılmamışsa, callback referansı değişsin veya değişmesin, her üst oluşturmada yine de yeniden oluşturulur. React.memo olmadan useCallback — faydasız maliyettir.
// ❌ Yararsız: alt öğede React.memo yok
const handle = useCallback(() => doStuff(), []);
<Child onClick={handle} />; // Child, React.memo olmadan yine de yeniden oluşturulur
// ❌ Eski kapanım: eksik bağımlılık
const handle = useCallback(() => {
console.log(count); // count her zaman 0 — eski kapanım!
}, []);
// ✅ Doğru: bağımlılıkları dahil et
const handle = useCallback(() => {
console.log(count);
}, [count]);
useCallback'teki eski kapanım (stale closure) sorunu, kullanılan tüm değişkenlerin bağımlılık dizisine dahil edilmesiyle çözülür. exhaustive-deps ile eslint-plugin-react-hooks, callback gövdesindeki tüm değişkenlerin dizide mevcut olup olmadığını otomatik olarak kontrol eder. Callback, oluşturmalar arasında değişmeyen setState'i kullanıyorsa, güvenle deps'e dahil edilebilir — React, setState'in kararlılığını garanti eder.
Sıkça Sorulan Sorular
Hayır. useCallback yalnızca üç durumda anlamlıdır: alt bileşen React.memo ile sarılmışsa, işlev useEffect bağımlılık dizisinde kullanılıyorsa veya işlev referans eşitliğine bağlı özel bir hook'a aktarılıyorsa. Diğer durumlarda, useCallback faydasız yük ekler. React ekibi, önce optimizasyon olmadan yazmayı ve profil oluşturma sonuçlarına göre eklemeyi önerir.
Basit bileşenler için — her oluşturmada yeni işlev biraz daha hızlıdır, çünkü useCallback bağımlılıkları karşılaştırmak ve dizi ayırmak için kaynak harcar. Derin React.memo ağaçları olan bileşenler için useCallback, binlerce alt öğenin yeniden oluşturulmasını önleyerek kazanır. Tahmin etmek yerine ölçün ve karşılaştırın — objektif değerlendirme için React DevTools Profiler kullanın.
Evet, useCallback async işlevlerle senkron işlevlerle tamamen aynı şekilde çalışır. Hook, işlevin kendisini belleğe alır ve sonuç (bir Promise) her çağrıldığında döndürülür. useCallback içindeki bir async işlev, useEffect'te kullanılan kararlı veri yükleme callback'leri için yaygın bir kalıptır: const fetchData = useCallback(async (id) => {...}, []).
React DevTools Profiler kullanın — hangi bileşenlerin yeniden oluşturulduğunu ve nedenini gösterir. Programatik kontrol için, console.log ekleyin veya useWhyDidYouUpdate kullanın — yeniden oluşturma nedenini günlükleyen bir kütüphane. Ana nedenler: bir prop değişti (callback referansı dahil), durum değişti veya bağlam değişti. useCallback yardımcı olmazsa — tüm bağımlılıkların doğru şekilde belirtildiğini kontrol edin.
React.memo olmasa bile, useCallback bağlam değerleri için useMemo ile kombinasyon halinde yararlı olabilir. Context.Provider'a işlevleri olan bir nesne aktarıyorsanız, nesne oluşturmayı useMemo'ye ve her işlevi useCallback'e sarın. Bu, işlevlerden biri değiştiğinde tüm bağlam tüketicilerinin yeniden oluşturulmasını önler. Ancak React.memo olmadan doğrudan props'ta callback'leri iletmek için useCallback'in faydası yoktur.
Özet
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.
Ayrıca okuyun