useCallback — mga pangunahing konsepto, hook ng memoization ng mga function sa React

May-akda: IT Sectr Nai-publish: 2026-07-04 Oras ng pagbabasa: 9 min

useCallback — ay isang React hook na nagbabalik ng naka-memoize na bersyon ng function, na hindi nagbabago sa pagitan ng mga render hangga't hindi nagbabago ang mga dependency nito. Hindi tulad ng karaniwang pagdedeklara ng function sa loob ng component (na gumagawa ng bagong function sa bawat render), pinapatatag ng useCallback ang reference sa function, na pumipigil sa mga hindi kinakailangang re-render ng mga child component na na-optimize sa pamamagitan ng React.memo. Ayon sa React Documentation (2025), ang useCallback ay kapaki-pakinabang lamang kapag isinama sa React.memo o sa mga hook na nakadepende sa matatag na reference.

Mga mahahalagang punto

  • useCallback — hook para sa memoization ng function, na nagpapanatili ng reference sa pagitan ng mga render.
  • React.memo — epektibo lamang ang useCallback kapag isinama sa React.memo upang maiwasan ang mga re-render.
  • Mga dependency — muling ginagawa ang function lamang kapag nagbago ang mga tinukoy na halaga sa array.
  • Matatag na reference — ginagarantiyahan ng useCallback na hindi magbabago ang reference sa function nang walang pangangailangan.
  • Huwag abusuhin — ang labis na useCallback nang walang React.memo ay nagpapalala ng performance.

Ano ang useCallback sa React

useCallback — ay isang hook na idinagdag sa React 16.8 na nag-memoize ng function: ibinabalik nito ang parehong reference hangga't hindi nagbabago ang mga dependency. Kung walang useCallback, ang bawat deklarasyon ng function sa loob ng component ay gumagawa ng bagong function object sa bawat render. Para sa mga primitive hindi ito napapansin, ngunit kapag ipinadala ang mga ganoong callback sa mga child component na na-optimize sa pamamagitan ng React.memo, ang bawat bagong reference ay nagdudulot ng re-render ng child component.

Sa sintaktikong paraan, ang useCallback ay katumbas ng useMemo para sa function: ang useCallback(fn, deps) — ay pinaikling bersyon ng useMemo(() => fn, deps). Iniimbak ng React ang naka-memoize na function sa panloob na imbakan ng fiber node at inihahambing ang mga dependency sa bawat render. Kung hindi nagbago ang mga dependency (Object.is para sa bawat elemento), ibinabalik ang dating function.

Ayon sa React Documentation — useCallback (2025), hindi kailangang balutin ang bawat function sa useCallback. May sariling presyo ang hook: ang pagtawag sa hook, paghahambing ng mga dependency, at paglalaan ng memorya para sa array ng mga dependency. Kung simple ang component at walang malalim na tree na may React.memo — pababagalin lamang ng useCallback ang application. Ang optimisasyon ay dapat masukat, hindi batay sa kutob.

jsx
import { useCallback } from 'react';

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

    // Matatag na reference — parehong function hanggang magbago ang deps
    const handleClick = useCallback(() => {
        setCount(prev => prev + 1);
    }, []);

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

Paano gumagana ang memoization ng mga function

Ang memoization sa useCallback ay nakabatay sa pag-cache ng resulta ng pagtawag sa function. Iniimbak ng React ang closure na ginawa sa unang render at ibinabalik ito sa mga susunod na render hangga't nananatiling hindi nagbabago ang mga dependency. Sa loob ng fiber node, ang bawat pagtawag sa useCallback ay gumagawa ng node sa naka-link na listahan ng mga hook, kung saan iniimbak ang mga dating dependency at ang naka-memoize na halaga.

Ang proseso ng paghahambing ng mga dependency ay ginagawa nang mahigpit sa pamamagitan ng Object.is — ito ay mababaw na paghahambing, nang walang malalim na pagsusuri ng mga object o array. Kung may object o array sa mga dependency, ang bagong reference sa bawat render ay ituturing na pagbabago. Kaya naman sa array ng mga dependency kailangang magpadala ng mga primitive na halaga o matatag na reference (halimbawa, mula sa useRef o useMemo).

Ayon sa React Core Team — Optimization Guide (2024), kasama sa halaga ng memoization ang tatlong sangkap: paglalaan ng array ng mga dependency sa bawat render, pag-ikot at paghahambing ng mga elemento sa pamamagitan ng Object.is, at potensyal na overhead ng garbage collection sa muling paggawa. Para sa component na may daan-daang useCallback wrapper ay maaari itong maging kapansin-pansin — kaya naman napakahalaga ng pagiging selektibo sa paggamit ng hook.

SenaryoWalang useCallbackMay useCallback
Paggawa ng functionBago sa bawat renderPareho sa matatag na deps
Pagpapadala sa React.memoNagre-render muli ang childHindi nagre-render muli ang child
Sa array ng useEffectInuulit ang effectMatatag ang effect
OverheadMinimalPaghahambing ng dependency + memorya

useCallback at performance

May malawakang mito na awtomatikong pinapabuti ng useCallback ang performance. Sa katotohanan, sa pag-iisa (nang walang React.memo) bahagyang pinapabagal pa nga ng useCallback ang application dahil sa halaga ng paghahambing ng mga dependency. Tunay na kapaki-pakinabang lamang ang hook sa tatlong senaryo: pagpigil sa mga re-render ng React.memo component, katatagan ng mga callback sa useEffect, at pagpapadala sa mga custom hook na nakadepende sa reference equality.

Simple lang ang tuntunin: hangga't hindi mo nakita ang problema sa performance sa pamamagitan ng React DevTools Profiler — huwag gamitin ang useCallback. Paulit-ulit na binigyang-diin ng React team na ang napaagang optimisasyon ay ugat ng kasamaan. Una sumulat ng malinis na code nang walang memoization, sukatin, hanapin ang bottleneck sa profiler, at saka lamang magdagdag ng useCallback kung saan talagang kailangan.

jsx
// Nasusukat na optimisasyon: Ang Child ay binalot sa React.memo
const Child = React.memo(({ onClick }) => {
    console.log('Na-re-render muli ang Child');
    return <button onClick={onClick}>Click</button>;
});

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

Ayon sa Dan Abramov — Before You memo() (2024), higit sa 90% ng mga kaso ng paggamit ng useCallback sa mga open-source na proyekto ay labis. Binabalot ng mga developer ang bawat function "kung sakali man", nang hindi sinusukat ang epekto. Alternatibo: kung mabigat ang child component at mahal ang re-render nito — makatwiran ang React.memo + useCallback. Kung magaan ang child component — mas mura ang re-render kaysa sa paghahambing ng mga dependency.

Kailan gagamitin ang useCallback

Unang senaryo — React.memo. Kung ang child component ay binalot sa React.memo at tumatanggap ng callback function bilang prop, nang walang useCallback ang child component ay muling ididrowing sa bawat render ng parent, kahit na hindi nagbago ang sarili nitong datos. Pinapatatag ng useCallback ang reference, at maaaring laktawan nang tama ng React.memo ang re-render.

Pangalawang senaryo — useEffect na may callback sa mga dependency. Kung ang function ay ipinadala sa array ng mga dependency ng useEffect, uulitin ng bawat bagong reference ang effect. Ginagarantiyahan ng useCallback na matatag ang reference, at ang effect ay tumatakbo lamang kapag nagbago ang tunay na datos, hindi sa bawat render. Ito ay lalong mahalaga para sa mga subscription at request.

  • React.memo children — pinipigilan ang re-render ng mga naka-memoize na child component kapag nagpapadala ng mga callback.
  • useEffect dependencies — pinapatatag ang function sa array ng mga dependency ng effect, na pumipigil sa mga labis na pag-ulit.
  • Mga custom hook — kung ang hook ay tumatanggap ng callback at nakadepende sa reference equality nito, kinakailangan ang useCallback.
  • Context value — kung may function na ipinapadala sa value ng context, pinapatatag ng useMemo kasama ang useCallback ang reference.
jsx
// useCallback para sa matatag na dependency ng useEffect
const fetchData = useCallback(async (id) => {
    const res = await fetch(`/api/${id}`);
    setData(res.data);
}, []); // matatag na reference, hindi na muling ginagawa

useEffect(() => {
    fetchData(props.id);
}, [props.id, fetchData]); // tumatakbo ang effect lamang kapag nagbago ang props.id

useCallback vs useMemo

Ang pangunahing pagkakaiba sa pagitan ng useCallback at useMemo ay kung ano ang ni-memoize ng bawat isa. Ni-memoize ng useCallback ang function: ibinabalik ng useCallback(fn, deps) ang fn (ang pareho o dating bersyon). Ni-memoize ng useMemo ang resulta ng pagtawag sa function: ibinabalik ng useMemo(() => computeExpensive(a, b), [a, b]) ang nakalkulang halaga, hindi ang function.

Sa teknikal na paraan, ang useCallback ay syntactic sugar sa itaas ng useMemo: ang useCallback(fn, deps) ay katumbas ng useMemo(() => fn, deps). Umiiral lamang ang sintaks na ito para sa kalinawan — upang malinaw na makita ng developer na ang ni-memoize ay ang mismong function, hindi ang halaga. Walang pagkakaiba sa performance sa pagitan ng useCallback at useMemo na may function — pareho ang code na nabubuo.

HookNi-memoizeSintaksPaggamit
useCallbackAng function (reference)useCallback(fn, deps)Mga callback para sa child component
useMemoAng resulta ng kalkulasyonuseMemo(() => value, deps)Mga mahal na kalkulasyon, memoization ng object
jsx
// Katumbas ang mga ito:
const handleClick = useCallback(() => doSomething(a, b), [a, b]);
const handleClick = useMemo(() => () => doSomething(a, b), [a, b]);

Mga karaniwang pagkakamali sa useCallback

Ang pinakakaraniwang pagkakamali — ang walang-katuturang pagbabalot ng lahat ng function sa useCallback nang walang React.memo sa mga child component. Kung ang child component ay hindi binalot sa React.memo, magre-render pa rin ito muli sa bawat render ng parent, anuman ang pagbabago ng reference ng callback. Ang useCallback na walang React.memo — gastos nang walang pakinabang.

  • useCallback na walang React.memo — nagre-render pa rin muli ang child component; walang katuturan ang optimisasyon.
  • Nakalimutang mga dependency — kung sa loob ng callback ay ginagamit ang variable na hindi nakalista sa deps, naglalaman ang callback ng stale closure.
  • Labis na memoization — pagbabalot ng bawat function, kabilang ang mga trivial onClick na may console.log.
  • Mga object at array sa mga dependency — ang bagong reference sa bawat render ay itinuturing na pagbabago, walang silbi ang memoization.
jsx
// ❌ Walang silbi: walang React.memo sa child
const handle = useCallback(() => doStuff(), []);
<Child onClick={handle} />; // Nagre-render pa rin muli ang Child nang walang React.memo

// ❌ Stale closure: kulang na dependency
const handle = useCallback(() => {
    console.log(count); // laging 0 ang count — stale closure!
}, []);

// ✅ Tama: isama ang mga dependency
const handle = useCallback(() => {
    console.log(count);
}, [count]);

Ang problema ng stale closure sa useCallback ay nalulutas sa pamamagitan ng paglilista ng lahat ng ginamit na variable sa array ng mga dependency. Awtomatikong tinitingnan ng eslint-plugin-react-hooks na may exhaustive-deps na ang lahat ng variable mula sa katawan ng callback ay nasa array. Kung gumagamit ang callback ng setState, na hindi nagbabago sa pagitan ng mga render, maaaring ligtas itong ilista sa deps — ginagarantiyahan ng React ang katatagan ng setState.

Mga madalas itanong

Kailangan bang balutin ang bawat function sa useCallback?

Hindi. Ang useCallback ay may katuturan lamang sa tatlong kaso: ang child component ay binalot sa React.memo, ang function ay ginagamit sa array ng mga dependency ng useEffect, o ang function ay ipinapadala sa custom hook na nakadepende sa reference equality. Sa ibang mga kaso, nagdaragdag ang useCallback ng overhead nang walang pakinabang. Inirerekomenda ng React team na sumulat muna nang walang optimisasyon at idagdag ang mga ito batay sa mga resulta ng profiling.

Alin ang mas mabilis — useCallback o bagong function sa bawat render?

Para sa mga simpleng component — bahagyang mas mabilis ang bagong function sa bawat render, dahil gumugugol ang useCallback ng mga mapagkukunan sa paghahambing ng mga dependency at paglalaan ng array. Para sa mga component na may malalim na React.memo tree — panalo ang useCallback, na pumipigil sa re-render ng libu-libong child element. Sukatin at ihambing, huwag manghula — gamitin ang React DevTools Profiler para sa obhetibong pagtatasa.

Maaari bang gamitin ang useCallback sa mga async function?

Oo, gumagana ang useCallback sa mga async function nang eksaktong katulad sa mga synchronous. Ni-memoize ng hook ang mismong function, at ang resulta (Promise) ay ibinabalik tuwing tatawagin. Ang asynchronous function sa loob ng useCallback ay karaniwang pattern para sa matatag na callback ng pag-load ng datos na ginagamit sa useEffect: const fetchData = useCallback(async (id) => {...}, []).

Paano i-debug ang problema sa useCallback at React.memo?

Gamitin ang React DevTools Profiler — ipapakita nito kung aling mga component ang nagre-render muli at kung bakit. Para sa programatikong pagsusuri magdagdag ng console.log o useWhyDidYouUpdate — library na nagla-log ng dahilan ng re-render. Mga pangunahing dahilan: nagbago ang isang prop (kabilang ang reference ng callback), nagbago ang state o context. Kung hindi nakakatulong ang useCallback — suriin kung tama ang pagkakalista ng lahat ng dependency.

Paano ipadala ang useCallback sa child component nang walang React.memo?

Kahit nang walang React.memo, maaaring maging kapaki-pakinabang ang useCallback sa kumbinasyon sa useMemo para sa value ng context. Kung nagpapadala ka ng object na may mga function sa Context.Provider, balutin ang paggawa ng object sa useMemo, at ang bawat function sa useCallback. Pipigilan nito ang re-render ng lahat ng konsyumer ng context kapag nagbago ang isa sa mga function. Ngunit para sa direktang pagpapadala ng mga callback sa props nang walang React.memo, walang pakinabang ang useCallback.

Konklusyon

  • useCallback — hook para sa memoization ng function, na nagbabalik ng matatag na reference hanggang magbago ang mga dependency.
  • React.memo synergy — epektibo lamang ang useCallback kapag isinama sa React.memo sa mga child component.
  • Paghahambing ng mga dependency — sa pamamagitan ng Object.is; sinisira ng mga object/array sa deps ang memoization.
  • Sukatin, huwag manghula — magdagdag ng useCallback lamang pagkatapos mahanap ang bottleneck sa pamamagitan ng profiler.
  • Stable closure — isama ang lahat ng ginamit na variable sa array ng mga dependency, kung hindi — stale closure.
  • useCallback vs useMemo — ni-memoize ng useCallback ang function, ang useMemo — ang resulta ng kalkulasyon.
  • Pagkalabis — higit sa 90% ng mga kaso ng paggamit ng useCallback sa mga totoong proyekto ay napaagang optimisasyon.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din