useCallback — əsas anlayışlar, React-də funksiyaların memorizasiya hook-u

Müəllif: IT Sectr Dərc olunub: 2026-07-04 Oxuma vaxtı: 9 dəq

useCallback — React hook-u, funksiyanın memorizasiya edilmiş versiyasını qaytarır; bu versiya dependency'lər dəyişməyənə qədər renderlər arasında dəyişmir. Komponent daxilində funksiyanın adi elanından (hər renderdə yeni funksiya yaradan) fərqli olaraq, useCallback funksiyaya istinadı stabilləşdirir və bu, React.memo vasitəsilə optimallaşdırılmış uşaq komponentlərin lazımsız re-renderinin qarşısını alır. React Documentation (2025) məlumatına görə, useCallback yalnız React.memo ilə birlikdə və ya sabit istinaddan asılı olan hook'larla işlədikdə faydalıdır.

Əsas məqamlar

  • useCallback — funksiyanı memorizasiya edən, renderlər arasında istinadı qoruyan hook.
  • React.memo — useCallback re-renderlərin qarşısını almaq üçün yalnız React.memo ilə birlikdə effektivdir.
  • Dependency'lər — funksiya yalnız massivdə göstərilən qiymətlər dəyişdikdə yenidən yaradılır.
  • Sabit istinad — useCallback funksiyaya istinadın lazımsız yerə dəyişməyəcəyini təmin edir.
  • Sui-istifadə etmə — React.memo olmadan həddən artıq useCallback performansı pisləşdirir.

React-də useCallback nədir

useCallback — React 16.8-ə əlavə edilmiş, funksiyanı memorizasiya edən hook-dur: dependency'lər dəyişməyənə qədər eyni istinadı qaytarır. useCallback olmadan komponent daxilində funksiyanın hər elanı hər renderdə yeni funksiya obyekti yaradır. Primitivlər üçün bu nəzərə çarpmır, lakin belə callback'ləri React.memo ilə optimallaşdırılmış uşaq komponentlərə ötürərkən hər yeni istinad uşaq komponentin re-renderinə səbəb olur.

Sintaktik olaraq useCallback funksiya üçün useMemo-ya ekvivalentdir: useCallback(fn, deps) — bu, useMemo(() => fn, deps) üçün qısaltmadır. React memorizasiya edilmiş funksiyanı fiber-qovşağın daxili yaddaşında saxlayır və hər renderdə dependency'ləri müqayisə edir. Dependency'lər dəyişməyibsə (hər element üçün Object.is), əvvəlki funksiya qaytarılır.

React Documentation — useCallback (2025) məlumatına görə, hər funksiyanı useCallback-ə bükmək lazım deyil. Hook-un öz qiyməti var: hook-un çağırılması, dependency'lərin müqayisəsi və dependency massivi üçün yaddaşın ayrılması. Komponent sadədirsə və React.memo ilə dərin ağacları yoxdursa — useCallback yalnız tətbiqi yavaşladacaq. Optimallaşdırma intuitiv deyil, ölçülə bilən olmalıdır.

jsx
import { useCallback } from 'react';

function Parent() {
    const [count, setCount] = useState(0);

    // Sabit istinad — deps dəyişənə qədər eyni funksiya
    const handleClick = useCallback(() => {
        setCount(prev => prev + 1);
    }, []);

    return <Child onClick={handleClick} />;
}

Funksiyaların memorizasiyası necə işləyir

useCallback-də memorizasiya funksiya çağırışının nəticəsinin keşləşdirilməsinə əsaslanır. React ilk render anında yaradılmış closure-u saxlayır və dependency'lər dəyişməz qaldıqca sonrakı renderlərdə onu qaytarır. Fiber-qovşağın daxilində hər useCallback çağırışı hook-ların bağlı siyahısında qovşaq yaradır; orada əvvəlki dependency'lər və memorizasiya edilmiş qiymət saxlanılır.

Dependency'lərin müqayisəsi prosesi ciddi şəkildə Object.is vasitəsilə aparılır — bu, obyektlərin və massivlərin dərindən yoxlanılması olmadan dayaz müqayisədir. Dependency'lərdə obyekt və ya massiv varsa, hər renderdəki yeni istinad dəyişiklik kimi qəbul ediləcək. Buna görə dependency massivində primitiv qiymətlər və ya sabit istinadlar (məsələn, useRef və ya useMemo-dan) ötürülməlidir.

React Core Team — Optimization Guide (2024) məlumatına görə, memorizasiyanın dəyəri üç komponentdən ibarətdir: hər renderdə dependency massivinin ayrılması, elementlərin Object.is vasitəsilə gəzilməsi və müqayisəsi və yenidən yaradılma zamanı garbage collector-un potensial yükü. Yüzlərlə useCallback bükməsi olan komponent üçün bu nəzərə çarpan ola bilər — buna görə hook-un istifadəsində seçicilik kritik əhəmiyyət daşıyır.

SsenariuseCallback olmadanuseCallback ilə
Funksiyanın yaradılmasıHər renderdə yeniSabit deps ilə eyni
React.memo-ya ötürülməUşaq re-render olunurUşaq re-render olunmur
useEffect massivindəEffekt yenidən işə düşürEffekt sabitdir
YükMinimalDependency müqayisəsi + yaddaş

useCallback və performans

Geniş yayılmış mif odur ki, useCallback avtomatik olaraq performansı yaxşılaşdırır. Əslində, təcrid halda (React.memo olmadan) useCallback dependency'lərin müqayisəsinin dəyərinə görə tətbiqi bir qədər də yavaşladır. Hook yalnız üç ssenaridə real fayda verir: React.memo komponentlərinin re-renderinin qarşısını almaq, useEffect-də callback'lərin sabitliyi və reference equality-dən asılı olan custom hook-lara ötürmə.

Qayda sadədir: React DevTools Profiler vasitəsilə performans problemi aşkar etməyincə — useCallback istifadə etmə. React komandası dəfələrlə vurğulayıb ki, vaxtından əvvəl optimallaşdırma pisliyin köküdür. Əvvəlcə memorizasiyasız təmiz kod yaz, ölç, profiler-də darboğazı tap və yalnız bundan sonra useCallback-i həqiqətən lazım olan yerdə əlavə et.

jsx
// Ölçülə bilən optimallaşdırma: Child React.memo-ya bükülüb
const Child = React.memo(({ onClick }) => {
    console.log('Child re-render olundu');
    return <button onClick={onClick}>Click</button>;
});

function Parent() {
    const handleClick = useCallback(() => {
        console.log('basıldı');
    }, []);
    return <Child onClick={handleClick} />;
}

Dan Abramov — Before You memo() (2024) məlumatına görə, open-source layihələrdə useCallback istifadəsinin 90%-dən çoxu artıqdır. Tərtibatçılar hər funksiyanı "ehtiyat üçün" bükür, effekti ölçmürlər. Alternativ: əgər uşaq komponent ağırdırsa və onun re-renderi bahalıdırsa — React.memo + useCallback əsaslıdır. Uşaq komponent yüngüldürsə — re-render dependency'lərin müqayisəsindən ucuzdur.

useCallback-dən nə vaxt istifadə etməli

Birinci ssenari — React.memo. Uşaq komponent React.memo-ya bükülübsə və prop kimi callback funksiyası qəbul edirsə, useCallback olmadan uşaq komponent öz məlumatları dəyişməsə belə, valideynin hər renderində yenidən çəkiləcək. useCallback istinadı stabilləşdirir və React.memo re-renderi düzgün atlaya bilir.

İkinci ssenari — dependency'lərdə callback olan useEffect. Funksiya useEffect-in dependency massivinə ötürülürsə, hər yeni istinad effekti yenidən işə salacaq. useCallback istinadın sabit olmasını təmin edir və effekt yalnız real məlumatlar dəyişdikdə işləyir, hər renderdə deyil. Bu, xüsusilə subscription və sorğular üçün vacibdir.

  • React.memo children — callback'lər ötürülərkən memorizasiya edilmiş uşaq komponentlərin re-renderinin qarşısını alır.
  • useEffect dependencies — funksiyanı effektin dependency massivində sabitləşdirir, lazımsız yenidən işə salmaların qarşısını alır.
  • Custom hook-lar — hook callback qəbul edirsə və onun reference equality-sindən asılıdırsa, useCallback mütləqdir.
  • Context value — kontekstin value-sunda funksiya ötürülürsə, useMemo useCallback ilə birlikdə istinadı sabitləşdirir.
jsx
// useCallback sabit useEffect dependency üçün
const fetchData = useCallback(async (id) => {
    const res = await fetch(`/api/${id}`);
    setData(res.data);
}, []); // sabit istinad, heç vaxt yenidən yaradılmır

useEffect(() => {
    fetchData(props.id);
}, [props.id, fetchData]); // effekt yalnız props.id dəyişdikdə işə düşür

useCallback vs useMemo

useCallback və useMemo arasındakı əsas fərq ondan ibarətdir ki, hər biri nəyi memorizasiya edir. useCallback funksiyanı memorizasiya edir: useCallback(fn, deps) fn-i (eyni və ya əvvəlki versiyanı) qaytarır. useMemo funksiya çağırışının nəticəsini memorizasiya edir: useMemo(() => computeExpensive(a, b), [a, b]) hesablanmış qiyməti qaytarır, funksiyanı yox.

Texniki olaraq useCallback useMemo üzərində sintaktik şəkərdir: useCallback(fn, deps) useMemo(() => fn, deps) ilə ekvivalentdir. Bu sintaksis yalnız oxunaqlılıq üçün mövcuddur — tərtibatçının aydın görməsi üçün ki, memorizasiya edilən dəyər yox, məhz funksiyadır. useCallback və funksiya ilə useMemo arasında performans fərqi yoxdur — onlar eyni kodu yaradırlar.

HookMemorizasiya edirSintaksisİstifadə
useCallbackFunksiyanı (istinadı)useCallback(fn, deps)Uşaq komponentlər üçün callback-lər
useMemoHesablamanın nəticəsiniuseMemo(() => value, deps)Bahalı hesablamalar, obyektlərin memorizasiyası
jsx
// Bunlar ekvivalentdir:
const handleClick = useCallback(() => doSomething(a, b), [a, b]);
const handleClick = useMemo(() => () => doSomething(a, b), [a, b]);

useCallback ilə tipik səhvlər

Ən geniş yayılmış səhv — bütün funksiyaları uşaq komponentlərdə React.memo olmadan useCallback-ə mənasız şəkildə bükməkdir. Uşaq komponent React.memo-ya bükülməyibsə, callback-ə istinadın dəyişməsindən asılı olmayaraq, yenə də valideynin hər renderində re-render olunacaq. React.memo olmadan useCallback — faydasız xərcdir.

  • React.memo olmadan useCallback — uşaq komponent yenə də re-render olunur; optimallaşdırma mənasızdır.
  • Unudulmuş dependency'lər — callback daxilində deps-də göstərilməyən dəyişən işlədilirsə, callback stale closure ehtiva edir.
  • Həddən artıq memorizasiya — console.log ilə trivial onClick daxil olmaqla hər funksiyanın bükülməsi.
  • Dependency'lərdə obyektlər və massivlər — hər renderdəki yeni istinad dəyişiklik kimi qəbul edilir, memorizasiya faydasızdır.
jsx
// ❌ Faydasız: child-da React.memo yoxdur
const handle = useCallback(() => doStuff(), []);
<Child onClick={handle} />; // Child React.memo olmadan yenə də re-render olunur

// ❌ Stale closure: dependency çatışmır
const handle = useCallback(() => {
    console.log(count); // count həmişə 0-dır — stale closure!
}, []);

// ✅ Düzgün: dependency'ləri daxil et
const handle = useCallback(() => {
    console.log(count);
}, [count]);

useCallback-də stale closure problemi dependency massivində istifadə olunan bütün dəyişənlərin göstərilməsi ilə həll olunur. exhaustive-deps ilə eslint-plugin-react-hooks avtomatik olaraq callback gövdəsindəki bütün dəyişənlərin massivdə olmasını yoxlayır. Callback renderlər arasında dəyişməyən setState işlədirsə, onu təhlükəsiz şəkildə deps-də göstərmək olar — React setState-in sabitliyinə zəmanət verir.

Tez-tez verilən suallar

Hər funksiyanı useCallback-ə bükmək lazımdırmı?

Xeyr. useCallback yalnız üç halda məna verir: uşaq komponent React.memo-ya bükülüb, funksiya useEffect-in dependency massivində istifadə olunur və ya funksiya reference equality-dən asılı olan custom hook-a ötürülür. Digər hallarda useCallback faydasız əlavə yük gətirir. React komandası əvvəlcə optimallaşdırmasız yazmağı və onları profilləmənin nəticələrinə görə əlavə etməyi tövsiyə edir.

Hansı daha sürətlidir — useCallback yoxsa hər renderdə yeni funksiya?

Sadə komponentlər üçün — hər renderdə yeni funksiya bir qədər sürətlidir, çünki useCallback dependency'lərin müqayisəsinə və massivin ayrılmasına resurs sərf edir. React.memo-nun dərin ağacları olan komponentlər üçün — useCallback qalib gəlir, minlərlə uşaq elementin re-renderinin qarşısını alır. Ölç və müqayisə et, təxmin etmə — obyektiv qiymətləndirmə üçün React DevTools Profiler istifadə et.

useCallback-i async funksiyalarla istifadə etmək olarmı?

Bəli, useCallback async funksiyalarla sinxron funksiyalarla eyni şəkildə işləyir. Hook funksiyanın özünü memorizasiya edir, nəticə (Promise) isə hər çağırışda qaytarılır. useCallback daxilindəki asinxron funksiya — useEffect-də istifadə olunan məlumat yükləmə callback'lərinin sabitliyi üçün geniş yayılmış naxışdır: const fetchData = useCallback(async (id) => {...}, []).

useCallback və React.memo ilə problemi necə debug etməli?

React DevTools Profiler istifadə et — hansı komponentlərin re-render olunduğunu və nə üçün olduğunu göstərəcək. Proqram yoxlaması üçün console.log və ya useWhyDidYouUpdate — re-renderin səbəbini qeyd edən kitabxana əlavə et. Əsas səbəblər: prop dəyişib (callback istinadı daxil olmaqla), state və ya kontekst dəyişib. useCallback kömək etmirsə — bütün dependency'lərin düzgün göstərildiyini yoxla.

useCallback-i React.memo olmadan uşaq komponentə necə ötürməli?

React.memo olmadan da useCallback kontekst value üçün useMemo ilə kombinasiyada faydalı ola bilər. Context.Provider-ə funksiyaları olan obyekt ötürürsənsə, obyektin yaradılmasını useMemo-ya, hər funksiyanı isə useCallback-ə bük. Bu, funksiyalardan birinin dəyişməsi zamanı kontekstin bütün istehlakçılarının re-renderinin qarşısını alır. Lakin React.memo olmadan proplara callback'lərin birbaşa ötürülməsində useCallback-in faydası yoxdur.

Yekun

  • useCallback — dependency'lər dəyişənə qədər sabit istinad qaytaran funksiya memorizasiya hook-u.
  • React.memo synergy — useCallback yalnız uşaq komponentlərdə React.memo ilə birlikdə effektivdir.
  • Dependency müqayisəsi — Object.is vasitəsilə; deps-də obyektlər/massivlər memorizasiyanı pozur.
  • Ölç, təxmin etmə — useCallback-i yalnız profiler vasitəsilə darboğaz aşkar etdikdən sonra əlavə et.
  • Stable closure — dependency massivinə istifadə olunan bütün dəyişənləri daxil et, əks halda — stale closure.
  • useCallback vs useMemo — useCallback funksiyanı memorizasiya edir, useMemo — hesablamanın nəticəsini.
  • Artıqlıq — real layihələrdə useCallback istifadəsinin 90%-dən çoxu vaxtından əvvəl optimallaşdırmadır.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun