useCallback — asosiy tushunchalar, React-da funksiyalarni memorizatsiya qilish hook-u

Muallif: IT Sectr Nashr etilgan: 2026-07-04 O'qish vaqti: 9 daq

useCallback — funksiyaning memorizatsiya qilingan versiyasini qaytaradigan React hook-i; bu versiya uning bog'liqliklari o'zgarmaguncha renderlar orasida o'zgarmaydi. Komponent ichida funksiyani odatiy e'lon qilishdan (har renderda yangi funksiya yaratadigan) farqli o'laroq, useCallback funksiyaga havolani barqarorlashtiradi, bu esa React.memo orqali optimallashtirilgan child komponentlarning keraksiz re-renderlarining oldini oladi. React Documentation (2025) ma'lumotlariga ko'ra, useCallback faqat React.memo bilan yoki barqaror havolaga bog'liq bo'lgan hook'lar bilan birgalikda foydalidir.

Asosiy narsalar

  • useCallback — funksiyani memorizatsiya qiluvchi, renderlar orasida havolani saqlaydigan hook.
  • React.memo — useCallback re-renderlarning oldini olish uchun faqat React.memo bilan birgalikda samarali.
  • Bog'liqliklar — funksiya faqat massivda ko'rsatilgan qiymatlar o'zgarganda qayta yaratiladi.
  • Barqaror havola — useCallback funksiyaga havola keraksiz o'zgarmasligini kafolatlaydi.
  • Suiiste'mol qilma — React.memo'siz ortiqcha useCallback ishlashni yomonlashtiradi.

React-da useCallback nima

useCallback — React 16.8 ga qo'shilgan, funksiyani memorizatsiya qiluvchi hook: bog'liqliklar o'zgarmaguncha xuddi shu havolani qaytaradi. useCallback'siz komponent ichida funksiyaning har bir e'loni har renderda yangi funksiya obyektini yaratadi. Primitivlar uchun bu sezilmaydi, lekin bunday callback'larni React.memo orqali optimallashtirilgan child komponentlarga uzatganda har bir yangi havola child komponentning re-renderiga sabab bo'ladi.

Sintaktik jihatdan useCallback funksiya uchun useMemo'ga teng: useCallback(fn, deps) — bu useMemo(() => fn, deps) uchun qisqartma. React memorizatsiya qilingan funksiyani fiber tugunining ichki xotirasida saqlaydi va har renderda bog'liqliklarni taqqoslaydi. Agar bog'liqliklar o'zgarmagan bo'lsa (har element uchun Object.is), avvalgi funksiya qaytariladi.

React Documentation — useCallback (2025) ma'lumotlariga ko'ra, har bir funksiyani useCallback'ga o'rash shart emas. Hook o'z narxiga ega: hook'ni chaqirish, bog'liqliklarni taqqoslash va bog'liqliklar massivi uchun xotira ajratish. Agar komponent sodda bo'lsa va React.memo bilan chuqur daraxtlarga ega bo'lmasa — useCallback faqat ilovani sekinlashtiradi. Optimallashtirish intuitiv emas, o'lchanadigan bo'lishi kerak.

jsx
import { useCallback } from 'react';

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

    // Barqaror havola — deps o'zgarmaguncha bir xil funksiya
    const handleClick = useCallback(() => {
        setCount(prev => prev + 1);
    }, []);

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

Funksiyalarni memorizatsiya qilish qanday ishlaydi

useCallback'dagi memorizatsiya funksiyani chaqirish natijasini keshlashga asoslangan. React birinchi render paytida yaratilgan closure'ni saqlab qoladi va bog'liqliklar o'zgarmaguncha keyingi renderlarda uni qaytaradi. Fiber tuguni ichida har bir useCallback chaqiruvi hook'lar bog'langan ro'yxatida tugun yaratadi; u yerda avvalgi bog'liqliklar va memorizatsiya qilingan qiymat saqlanadi.

Bog'liqliklarni taqqoslash jarayoni qat'iy ravishda Object.is orqali amalga oshiriladi — bu obyektlar yoki massivlarni chuqur tekshirmasdan sayoz taqqoslashdir. Agar bog'liqliklarda obyekt yoki massiv bo'lsa, har renderdagi yangi havola o'zgarish deb hisoblanadi. Shuning uchun bog'liqliklar massiviga primitiv qiymatlar yoki barqaror havolalar (masalan, useRef yoki useMemo'dan) uzatish kerak.

React Core Team — Optimization Guide (2024) ma'lumotlariga ko'ra, memorizatsiya narxi uch komponentdan iborat: har renderda bog'liqliklar massivini ajratish, elementlarni Object.is orqali aylanib taqqoslash va qayta yaratishda garbage collector'ning potensial yuki. Yuzlab useCallback o'ramlariga ega komponent uchun bu sezilarli bo'lishi mumkin — shuning uchun hook'ni qo'llashda tanlanganlik muhim ahamiyatga ega.

SsenariyuseCallback'sizuseCallback bilan
Funksiya yaratishHar renderda yangiBarqaror deps bilan bir xil
React.memo'ga uzatishChild re-render bo'ladiChild re-render bo'lmaydi
useEffect massividaEffekt qayta ishga tushadiEffekt barqaror
YuklamaMinimalBog'liqliklarni taqqoslash + xotira

useCallback va ishlash

Keng tarqalgan afsona shundaki, useCallback ishlashni avtomatik yaxshilaydi. Aslida, yakkalangan holda (React.memo'siz) useCallback bog'liqliklarni taqqoslash narxi tufayli ilovani biroz sekinlashtiradi. Hook faqat uchta ssenariyda haqiqiy foyda keltiradi: React.memo komponentlarining re-renderini oldini olish, useEffect'dagi callback'larning barqarorligi va reference equality'ga bog'liq bo'lgan custom hook'larga uzatish.

Qoida sodda: React DevTools Profiler orqali ishlash muammosini aniqlamaguningizcha — useCallback'dan foydalanmang. React jamoasi qayta-qayta ta'kidlagan: vaqtidan oldin optimallashtirish yomonlikning ildizidir. Avval memorizatsiyasiz toza kod yozing, o'lchang, profilerda tor joyni toping va shundan keyingina useCallback'ni haqiqatan kerak bo'lgan joyga qo'shing.

jsx
// O'lchanadigan optimallashtirish: Child React.memo'ga o'ralgan
const Child = React.memo(({ onClick }) => {
    console.log('Child re-render bo'ldi');
    return <button onClick={onClick}>Click</button>;
});

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

Dan Abramov — Before You memo() (2024) ma'lumotlariga ko'ra, open-source loyihalarda useCallback qo'llanishining 90 foizdan ortig'i ortiqcha. Dasturchilar har bir funksiyani ehtiyot uchun o'rab, effektni o'lchamaydilar. Muqobil: agar child komponent og'ir bo'lsa va uning re-renderi qimmat bo'lsa — React.memo + useCallback asosli. Agar child komponent yengil bo'lsa — re-render bog'liqliklarni taqqoslashdan arzon.

useCallback-dan qachon foydalanish kerak

Birinchi ssenariy — React.memo. Agar child komponent React.memo'ga o'ralgan bo'lsa va prop sifatida callback funksiyasini qabul qilsa, useCallback'siz child komponent o'z ma'lumotlari o'zgarmagan bo'lsa ham, ota-onaning har renderida qayta chiziladi. useCallback havolani barqarorlashtiradi va React.memo re-renderni to'g'ri o'tkazib yubora oladi.

Ikkinchi ssenariy — bog'liqliklarda callback bo'lgan useEffect. Agar funksiya useEffect bog'liqliklari massiviga uzatilsa, har bir yangi havola effektni qayta ishga tushiradi. useCallback havolaning barqarorligini kafolatlaydi va effekt faqat real ma'lumotlar o'zgarganda ishlaydi, har renderda emas. Bu ayniqsa subscription va so'rovlar uchun muhim.

  • React.memo children — callback'lar uzatilganda memorizatsiya qilingan child komponentlar re-renderining oldini oladi.
  • useEffect dependencies — funksiyani effekt bog'liqliklari massivida barqarorlashtiradi, ortiqcha qayta ishga tushirishlarning oldini oladi.
  • Custom hook'lar — agar hook callback qabul qilsa va uning reference equality'siga bog'liq bo'lsa, useCallback majburiy.
  • Context value — agar kontekst value'siga funksiya uzatilsa, useMemo useCallback bilan birga havolani barqarorlashtiradi.
jsx
// useCallback barqaror useEffect bog'liqligi uchun
const fetchData = useCallback(async (id) => {
    const res = await fetch(`/api/${id}`);
    setData(res.data);
}, []); // barqaror havola, hech qachon qayta yaratilmaydi

useEffect(() => {
    fetchData(props.id);
}, [props.id, fetchData]); // effekt faqat props.id o'zgarganda ishlaydi

useCallback vs useMemo

useCallback va useMemo o'rtasidagi asosiy farq — har biri nimani memorizatsiya qilishida. useCallback funksiyani memorizatsiya qiladi: useCallback(fn, deps) fn ni (xuddi shu yoki avvalgi versiyani) qaytaradi. useMemo funksiyani chaqirish natijasini memorizatsiya qiladi: useMemo(() => computeExpensive(a, b), [a, b]) hisoblangan qiymatni qaytaradi, funksiyani emas.

Texnik jihatdan useCallback useMemo ustidagi sintaktik shakar: useCallback(fn, deps) useMemo(() => fn, deps) bilan teng. Bu sintaksis faqat o'qilishi uchun mavjud — dasturchi aniq ko'rishi uchunki, memorizatsiya qilinayotgan narsa qiymat emas, aynan funksiya. useCallback va funksiyali useMemo o'rtasida ishlash farqi yo'q — ular bir xil kodni yaratadi.

HookMemorizatsiya qiladiSintaksisQo'llanilishi
useCallbackFunksiyani (havolani)useCallback(fn, deps)Child komponentlar uchun callback'lar
useMemoHisoblash natijasiniuseMemo(() => value, deps)Qimmat hisoblashlar, obyektlarni memorizatsiya qilish
jsx
// Bular ekvivalent:
const handleClick = useCallback(() => doSomething(a, b), [a, b]);
const handleClick = useMemo(() => () => doSomething(a, b), [a, b]);

useCallback bilan odatiy xatolar

Eng keng tarqalgan xato — barcha funksiyalarni child komponentlarda React.memo'siz useCallback'ga ma'nosiz o'rash. Agar child komponent React.memo'ga o'ralmagan bo'lsa, u callback havolasi o'zgarishidan qat'i nazar, har holda ota-onaning har renderida re-render bo'ladi. React.memo'siz useCallback — foydasiz xarajat.

  • React.memo'siz useCallback — child komponent baribir re-render bo'ladi; optimallashtirish ma'nosiz.
  • Unutilgan bog'liqliklar — agar callback ichida deps'da ko'rsatilmagan o'zgaruvchi ishlatilsa, callback stale closure'ni o'z ichiga oladi.
  • Ortiqcha memorizatsiya — console.log bilan trivial onClick'lar ham bo'lgan har bir funksiyani o'rash.
  • Bog'liqliklarda obyektlar va massivlar — har renderdagi yangi havola o'zgarish deb hisoblanadi, memorizatsiya foydasiz.
jsx
// ❌ Foydasiz: child'da React.memo yo'q
const handle = useCallback(() => doStuff(), []);
<Child onClick={handle} />; // Child React.memo'siz baribir re-render bo'ladi

// ❌ Stale closure: bog'liqlik yetishmayapti
const handle = useCallback(() => {
    console.log(count); // count doim 0 — stale closure!
}, []);

// ✅ To'g'ri: bog'liqliklarni kiriting
const handle = useCallback(() => {
    console.log(count);
}, [count]);

useCallback'dagi stale closure muammosi bog'liqliklar massiviga ishlatiladigan barcha o'zgaruvchilarni kiritish bilan hal qilinadi. exhaustive-deps bilan eslint-plugin-react-hooks callback tanasidagi barcha o'zgaruvchilarning massivda borligini avtomatik tekshiradi. Agar callback renderlar orasida o'zgarmaydigan setState'ni ishlatsa, uni deps'da xavfsiz ko'rsatish mumkin — React setState'ning barqarorligini kafolatlaydi.

Tez-tez so'raladigan savollar

Har bir funksiyani useCallback'ga o'rash kerakmi?

Yo'q. useCallback faqat uchta holatda ma'noga ega: child komponent React.memo'ga o'ralgan, funksiya useEffect bog'liqliklari massivida ishlatiladi yoki funksiya reference equality'ga bog'liq custom hook'ga uzatiladi. Boshqa holatlarda useCallback foydasiz yuklama qo'shadi. React jamoasi avval optimallashtirishsiz yozishni va ularni profillash natijalariga ko'ra qo'shishni tavsiya qiladi.

Qaysi biri tezroq — useCallback yoki har renderda yangi funksiya?

Oddiy komponentlar uchun — har renderda yangi funksiya biroz tezroq, chunki useCallback bog'liqliklarni taqqoslash va massiv ajratishga resurs sarflaydi. React.memo'ning chuqur daraxtlariga ega komponentlar uchun — useCallback g'alaba qozonadi, minglab child elementlarning re-renderini oldini oladi. O'lchang va solishtiring, taxmin qilmang — obyektiv baholash uchun React DevTools Profiler'dan foydalaning.

useCallback'ni async funksiyalar bilan ishlatish mumkinmi?

Ha, useCallback async funksiyalar bilan sinxron funksiyalar kabi ishlaydi. Hook funksiyaning o'zini memorizatsiya qiladi, natija (Promise) esa har chaqiruvda qaytariladi. useCallback ichidagi asinxron funksiya — useEffect'da ishlatiladigan barqaror ma'lumot yuklash callback'larining keng tarqalgan namunasi: const fetchData = useCallback(async (id) => {...}, []).

useCallback va React.memo bilan muammoni qanday tuzatish (debug) kerak?

React DevTools Profiler'dan foydalaning — qaysi komponentlar re-render bo'layotganini va nima uchun ekanini ko'rsatadi. Dasturiy tekshirish uchun console.log yoki useWhyDidYouUpdate — re-render sababini qayd etuvchi kutubxonani qo'shing. Asosiy sabablar: prop o'zgargan (callback havolasi ham), state yoki kontekst o'zgargan. Agar useCallback yordam bermasa — barcha bog'liqliklar to'g'ri ko'rsatilganini tekshiring.

useCallback'ni React.memo'siz child komponentga qanday uzatish kerak?

React.memo'siz ham useCallback kontekst value uchun useMemo bilan kombinatsiyada foydali bo'lishi mumkin. Agar Context.Provider'ga funksiyalari bo'lgan obyekt uzatayotgan bo'lsangiz, obyekt yaratishni useMemo'ga, har bir funksiyani esa useCallback'ga o'rang. Bu funksiyalardan biri o'zgarganda kontekstning barcha iste'molchilari re-renderining oldini oladi. Lekin React.memo'siz props'ga callback'larni to'g'ridan-to'g'ri uzatishda useCallback foyda keltirmaydi.

Xulosa

  • useCallback — bog'liqliklar o'zgarmaguncha barqaror havola qaytaruvchi funksiya memorizatsiya hook'i.
  • React.memo synergy — useCallback faqat child komponentlarda React.memo bilan birgalikda samarali.
  • Bog'liqliklarni taqqoslash — Object.is orqali; deps'dagi obyektlar/massivlar memorizatsiyani buzadi.
  • O'lchang, taxmin qilmang — useCallback'ni faqat profiler orqali tor joy topilgandan keyin qo'shing.
  • Stable closure — bog'liqliklar massiviga ishlatiladigan barcha o'zgaruvchilarni kiriting, aks holda — stale closure.
  • useCallback vs useMemo — useCallback funksiyani memorizatsiya qiladi, useMemo — hisoblash natijasini.
  • Ortiqchalik — real loyihalarda useCallback qo'llanishining 90 foizdan ortig'i vaqtidan oldin optimallashtirishdir.

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing