useCallback হল একটি React হুক যা একটি ফাংশনের মেমোইজড সংস্করণ ফেরত দেয় যা রেন্ডারগুলির মধ্যে পরিবর্তিত হয় না যতক্ষণ না এর নির্ভরতাগুলি পরিবর্তিত হয়। কম্পোনেন্টের ভিতরে সাধারণ ফাংশন ঘোষণা (যা প্রতি রেন্ডারে একটি নতুন ফাংশন তৈরি করে) থেকে ভিন্ন, useCallback ফাংশন রেফারেন্সকে স্থিতিশীল করে, যা React.memo-এর মাধ্যমে অপ্টিমাইজ করা চাইল্ড কম্পোনেন্টের অপ্রয়োজনীয় রি-রেন্ডার প্রতিরোধ করে। React Documentation (2025) অনুসারে, useCallback শুধুমাত্র React.memo বা স্থিতিশীল রেফারেন্সের উপর নির্ভরশীল হুকগুলির সাথে জোড়ায় কার্যকর।
মূল পয়েন্ট
useCallback হল React 16.8-এ যোগ করা একটি হুক যা একটি ফাংশন মেমোইজ করে: নির্ভরতা পরিবর্তন না হওয়া পর্যন্ত একই রেফারেন্স ফেরত দেয়। useCallback ছাড়া, কম্পোনেন্টের ভিতরে প্রতিটি ফাংশন ঘোষণা প্রতি রেন্ডারে একটি নতুন ফাংশন অবজেক্ট তৈরি করে। প্রিমিটিভের জন্য এটি অলক্ষিত, কিন্তু React.memo-এর মাধ্যমে অপ্টিমাইজ করা চাইল্ড কম্পোনেন্টে এই কলব্যাকগুলি পাস করার সময়, প্রতিটি নতুন রেফারেন্স চাইল্ড কম্পোনেন্টের রি-রেন্ডার ঘটায়।
সিনট্যাক্টিকভাবে, useCallback একটি ফাংশনের জন্য useMemo-এর সমতুল্য: useCallback(fn, deps) হল useMemo(() => fn, deps)-এর শর্টহ্যান্ড। React মেমোইজড ফাংশনটি ফাইবার নোডের অভ্যন্তরীণ স্টোরেজে রাখে এবং প্রতি রেন্ডারে নির্ভরতা তুলনা করে। যদি নির্ভরতাগুলি পরিবর্তিত না হয় (প্রत्यেক আইটেমের জন্য Object.is), তাহলে আগের ফাংশনটি ফেরত দেওয়া হয়।
React Documentation — useCallback (2025) অনুসারে, প্রতিটি ফাংশনকে useCallback-এ মোড়ানো উচিত নয়। হুকের নিজস্ব খরচ আছে: হুক কল করা, নির্ভরতা তুলনা করা এবং নির্ভরতা অ্যারের জন্য মেমোরি বরাদ্দ করা। যদি কম্পোনেন্টটি সহজ হয় এবং React.memo-এর সাথে গভীর ট্রি না থাকে, তাহলে useCallback শুধুমাত্র অ্যাপ্লিকেশনকে ধীর করবে। অপ্টিমাইজেশন পরিমাপযোগ্য হওয়া উচিত, স্বজ্ঞাত নয়।
import { useCallback } from 'react';
function Parent() {
const [count, setCount] = useState(0);
// স্থিতিশীল রেফারেন্স — নির্ভরতা পরিবর্তন না হওয়া পর্যন্ত একই ফাংশন
const handleClick = useCallback(() => {
setCount(prev => prev + 1);
}, []);
return <Child onClick={handleClick} />;
}
useCallback-এ মেমোইজেশন ফাংশন কলের ফলাফল ক্যাশ করার উপর ভিত্তি করে তৈরি। React প্রথম রেন্ডারের সময় তৈরি ক্লোজারটি সংরক্ষণ করে এবং পরবর্তী রেন্ডারগুলিতে এটি ফেরত দেয় যতক্ষণ নির্ভরতা অপরিবর্তিত থাকে। ফাইবার নোডের ভিতরে, প্রতিটি useCallback কল হুকের লিঙ্কড লিস্টে একটি নোড তৈরি করে, যেখানে আগের নির্ভরতা এবং মেমোইজড মান সংরক্ষিত হয়।
নির্ভরতা তুলনা কঠোরভাবে Object.is-এর মাধ্যমে করা হয় — অবজেক্ট বা অ্যারের গভীর পরীক্ষা ছাড়াই একটি ভাসা ভাসা তুলনা। যদি নির্ভরতায় কোনো অবজেক্ট বা অ্যারে থাকে, তাহলে প্রতি রেন্ডারে একটি নতুন রেফারেন্স পরিবর্তন হিসেবে গণ্য হবে। তাই, নির্ভরতা অ্যারেতে প্রিমিটিভ মান বা স্থিতিশীল রেফারেন্স (যেমন useRef বা useMemo থেকে) থাকা উচিত।
React Core Team — Optimization Guide (2024) অনুসারে, মেমোইজেশনের খরচ তিনটি উপাদান অন্তর্ভুক্ত করে: প্রতি রেন্ডারে নির্ভরতা অ্যারে বরাদ্দ করা, Object.is-এর মাধ্যমে উপাদানগুলি অতিক্রম করা এবং তুলনা করা, এবং পুনঃনির্মাণে আবর্জনা সংগ্রহ ওভারহেড। শত শত useCallback র্যাপারযুক্ত কম্পোনেন্টের জন্য, এটি লক্ষণীয় হতে পারে — তাই হুক ব্যবহারে নির্বাচনশীলতা গুরুত্বপূর্ণ।
| পরিস্থিতি | useCallback ছাড়া | useCallback-সহ |
|---|---|---|
| ফাংশন তৈরি | প্রতি রেন্ডারে নতুন | স্থিতিশীল deps-এ একই |
| React.memo-এ পাস | চাইল্ড রি-রেন্ডার করে | চাইল্ড রি-রেন্ডার করে না |
| useEffect অ্যারেতে | ইফেক্ট পুনরায় শুরু হয় | ইফেক্ট স্থিতিশীল |
| ওভারহেড | সর্বনিম্ন | নির্ভরতা তুলনা + মেমোরি |
একটি ব্যাপক ভুল ধারণা আছে যে useCallback স্বয়ংক্রিয়ভাবে পারফরম্যান্স উন্নত করে। বাস্তবে, বিচ্ছিন্নভাবে (React.memo ছাড়া), useCallback নির্ভরতা তুলনার খরচের কারণে অ্যাপ্লিকেশনকে কিছুটা ধীরও করে। হুকটি শুধুমাত্র তিনটি পরিস্থিতিতে প্রকৃত সুবিধা দেয়: React.memo কম্পোনেন্টের রি-রেন্ডার প্রতিরোধ, useEffect-এ কলব্যাক স্থিতিশীল করা, এবং কাস্টম হুকগুলিতে কলব্যাক পাস করা যা রেফারেন্স সমতার উপর নির্ভর করে।
নিয়মটি সহজ: যতক্ষণ না আপনি React DevTools Profiler-এর মাধ্যমে পারফরম্যান্স সমস্যা সনাক্ত করছেন — useCallback ব্যবহার করবেন না। React টিম বারবার জোর দিয়েছে যে অকাল অপ্টিমাইজেশন是所有 মন্দের মূল। প্রথমে মেমোইজেশন ছাড়া পরিষ্কার কোড লিখুন, মাপুন, প্রোফাইলারে বাধা খুঁজুন, এবং তারপরেই useCallback যোগ করুন যেখানে সত্যিই প্রয়োজন।
// পরিমাপযোগ্য অপ্টিমাইজেশন: Child React.memo-এ মোড়ানো
const Child = React.memo(({ onClick }) => {
console.log('Child পুনরায় রেন্ডার হয়েছে');
return <button onClick={onClick}>Click</button>;
});
function Parent() {
const handleClick = useCallback(() => {
console.log('ক্লিক করা হয়েছে');
}, []);
return <Child onClick={handleClick} />;
}
Dan Abramov — Before You memo() (2024) অনুসারে, ওপেন-সোর্স প্রকল্পে useCallback-এর 90% এর বেশি ব্যবহার অপ্রয়োজনীয়। ডেভেলপাররা প্রভাব মাপা ছাড়াই "যদি প্রয়োজন হয়" বলে প্রতিটি ফাংশন মোড়ায়। বিকল্প: যদি চাইল্ড কম্পোনেন্ট ভারী হয় এবং তার রি-রেন্ডার ব্যয়বহুল হয় — React.memo + useCallback ন্যায্য। যদি চাইল্ড কম্পোনেন্ট হালকা হয় — রি-রেন্ডার নির্ভরতা তুলনার চেয়ে সস্তা।
প্রথম পরিস্থিতি — React.memo। যদি চাইল্ড কম্পোনেন্ট React.memo-এ মোড়ানো হয় এবং একটি প্রপ হিসেবে কলব্যাক ফাংশন গ্রহণ করে, useCallback ছাড়া চাইল্ড কম্পোনেন্ট প্রতি প্যারেন্ট রেন্ডারে রি-রেন্ডার করবে, এমনকি যদি তার নিজস্ব ডেটা পরিবর্তিত না হয়। useCallback রেফারেন্স স্থিতিশীল করে, যা React.memo-কে রি-রেন্ডার সঠিকভাবে এড়াতে দেয়।
দ্বিতীয় পরিস্থিতি — নির্ভরতায় কলব্যাক-সহ useEffect। যদি কোনো ফাংশন useEffect নির্ভরতা অ্যারেতে পাস করা হয়, প্রতিটি নতুন রেফারেন্স ইফেক্টটি পুনরায় শুরু করবে। useCallback নিশ্চিত করে যে রেফারেন্স স্থিতিশীল, এবং ইফেক্টটি কেবল তখনই চলে যখন প্রকৃত ডেটা পরিবর্তিত হয়, প্রতি রেন্ডারে নয়। এটি বিশেষ করে সাবস্ক্রিপশন এবং অনুরোধের জন্য গুরুত্বপূর্ণ।
// স্থিতিশীল useEffect নির্ভরতার জন্য useCallback
const fetchData = useCallback(async (id) => {
const res = await fetch(`/api/${id}`);
setData(res.data);
}, []); // স্থিতিশীল রেফারেন্স, কখনও পুনরায় তৈরি হয় না
useEffect(() => {
fetchData(props.id);
}, [props.id, fetchData]); // ইফেক্ট কেবল তখন চলে যখন props.id পরিবর্তিত হয়
useCallback এবং useMemo-র মধ্যে প্রধান পার্থক্য হল প্রতিটি কী মেমোইজ করে। useCallback একটি ফাংশন মেমোইজ করে: useCallback(fn, deps) fn ফেরত দেয় (একই বা আগের সংস্করণ)। useMemo একটি ফাংশন কলের ফলাফল মেমোইজ করে: useMemo(() => computeExpensive(a, b), [a, b]) গণনা করা মান ফেরত দেয়, ফাংশন নয়।
প্রযুক্তিগতভাবে, useCallback হল useMemo-র উপর সিনট্যাক্টিক সুগার: useCallback(fn, deps) হল useMemo(() => fn, deps)-এর সমতুল্য। এই সিনট্যাক্সটি শুধুমাত্র পঠনযোগ্যতার জন্য বিদ্যমান — যাতে ডেভেলপার স্পষ্টভাবে দেখতে পারে যে একটি ফাংশন মেমোইজ করা হচ্ছে, কোনো মান নয়। useCallback এবং ফাংশন-সহ useMemo-র মধ্যে পারফরম্যান্সে কোনো পার্থক্য নেই — তারা একই কোড তৈরি করে।
| হুক | মেমোইজ করে | সিনট্যাক্স | ব্যবহার |
|---|---|---|---|
| useCallback | ফাংশন (রেফারেন্স) | useCallback(fn, deps) | চাইল্ড কম্পোনেন্টের জন্য কলব্যাক |
| useMemo | গণনা ফলাফল | useMemo(() => value, deps) | ব্যয়বহুল গণনা, অবজেক্ট মেমোইজেশন |
// এগুলি সমতুল্য:
const handleClick = useCallback(() => doSomething(a, b), [a, b]);
const handleClick = useMemo(() => () => doSomething(a, b), [a, b]);
সবচেয়ে সাধারণ ভুল হল চাইল্ড কম্পোনেন্টে React.memo ছাড়া সব ফাংশনকে useCallback-এ অর্থহীনভাবে মোড়ানো। যদি চাইল্ড কম্পোনেন্ট React.memo-এ মোড়ানো না হয়, তাহলে এটি প্রতি প্যারেন্ট রেন্ডারে এখনও রি-রেন্ডার করবে, কলব্যাক রেফারেন্স পরিবর্তিত হোক বা না হোক। React.memo ছাড়া useCallback — খরচ ছাড়া লাভ নেই।
// ❌ অকেজো: চাইল্ডে React.memo নেই
const handle = useCallback(() => doStuff(), []);
<Child onClick={handle} />; // Child React.memo ছাড়া এখনও রি-রেন্ডার করে
// ❌ স্টেল ক্লোজার: নির্ভরতা অনুপস্থিত
const handle = useCallback(() => {
console.log(count); // count সবসময় 0 — স্টেল ক্লোজার!
}, []);
// ✅ সঠিক: নির্ভরতা অন্তর্ভুক্ত করুন
const handle = useCallback(() => {
console.log(count);
}, [count]);
useCallback-এ স্টেল ক্লোজার সমস্যা নির্ভরতা অ্যারেতে সব ব্যবহৃত ভেরিয়েবল অন্তর্ভুক্ত করে সমাধান করা হয়। exhaustive-deps-সহ eslint-plugin-react-hooks স্বয়ংক্রিয়ভাবে পরীক্ষা করে যে কলব্যাক বডির সব ভেরিয়েবল অ্যারেতে উপস্থিত আছে। যদি কলব্যাক setState ব্যবহার করে, যা রেন্ডারগুলির মধ্যে পরিবর্তিত হয় না, তাহলে এটি নিরাপদে deps-এ অন্তর্ভুক্ত করা যেতে পারে — React setState-এর স্থিতিশীলতা নিশ্চিত করে।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
না। useCallback শুধুমাত্র তিনটি ক্ষেত্রে অর্থপূর্ণ: চাইল্ড কম্পোনেন্ট React.memo-এ মোড়ানো, ফাংশনটি useEffect নির্ভরতা অ্যারেতে ব্যবহৃত, বা ফাংশনটি কাস্টম হুকে পাস করা যা রেফারেন্স সমতার উপর নির্ভর করে। অন্যান্য ক্ষেত্রে, useCallback লাভ ছাড়া ওভারহেড যোগ করে। React টিম প্রথমে অপ্টিমাইজেশন ছাড়া লিখতে এবং প্রোফাইলিং ফলাফলের ভিত্তিতে সেগুলি যোগ করতে সুপারিশ করে।
সরল কম্পোনেন্টের জন্য — প্রতি রেন্ডারে নতুন ফাংশন কিছুটা দ্রুত, কারণ useCallback নির্ভরতা তুলনা এবং অ্যারে বরাদ্দে সম্পদ ব্যয় করে। গভীর React.memo ট্রি-যুক্ত কম্পোনেন্টের জন্য, useCallback হাজার হাজার চাইল্ড এলিমেন্টের রি-রেন্ডার প্রতিরোধ করে জয়ী হয়। অনুমান করার পরিবর্তে মাপুন এবং তুলনা করুন — বস্তুনিষ্ঠ মূল্যায়নের জন্য React DevTools Profiler ব্যবহার করুন।
হ্যাঁ, useCallback async ফাংশনের সাথে ঠিক একইভাবে কাজ করে যেমন সিনক্রোনাস ফাংশনের সাথে। হুক ফাংশনটি নিজেই মেমোইজ করে, এবং ফলাফল (Promise) প্রতিবার কল করার সময় ফেরত দেওয়া হয়। useCallback-এর ভিতরে async ফাংশন useEffect-এ ব্যবহৃত স্থিতিশীল ডেটা লোডিং কলব্যাকের জন্য একটি সাধারণ প্যাটার্ন: const fetchData = useCallback(async (id) => {...}, [])।
React DevTools Profiler ব্যবহার করুন — এটি দেখায় কোন কম্পোনেন্ট রি-রেন্ডার করে এবং কেন। প্রোগ্রাম্যাটিক পরীক্ষার জন্য, console.log যোগ করুন বা useWhyDidYouUpdate ব্যবহার করুন — একটি লাইব্রেরি যা রি-রেন্ডারের কারণ লগ করে। প্রধান কারণ: প্রপ পরিবর্তিত (কলব্যাক রেফারেন্স সহ), স্টেট পরিবর্তিত, বা কনটেক্সট পরিবর্তিত। যদি useCallback সাহায্য না করে — পরীক্ষা করুন যে সব নির্ভরতা সঠিকভাবে নির্দিষ্ট করা আছে।
React.memo ছাড়াও, useCallback কনটেক্সট মানের জন্য useMemo-র সাথে দরকারী হতে পারে। যদি আপনি Context.Provider-এ ফাংশন-সহ একটি অবজেক্ট পাস করেন, তাহলে অবজেক্ট তৈরি useMemo-এ এবং প্রতিটি ফাংশন useCallback-এ মোড়ান। এটি একটি ফাংশন পরিবর্তিত হলে সব কনটেক্সট ভোক্তার রি-রেন্ডার প্রতিরোধ করে। কিন্তু React.memo ছাড়া সরাসরি প্রপস-এ কলব্যাক পাস করার ক্ষেত্রে useCallback-এর কোনো লাভ নেই।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন