useEffect হল একটি React হুক যা ফাংশনাল কম্পোনেন্টে সাইড ইফেক্ট সম্পাদনের অনুমতি দেয়, ক্লাস কম্পোনেন্টের জীবনচক্র পদ্ধতিগুলি প্রতিস্থাপন করে: componentDidMount, componentDidUpdate এবং componentWillUnmount। React Documentation (2025) অনুসারে, useEffect React DOM-এ পরিবর্তনগুলি কমিট করার পরে কার্যকর হয়, যা প্রকৃত DOM ট্রিতে অ্যাক্সেস নিশ্চিত করে। হুকটি একটি ইফেক্ট ফাংশন এবং একটি ঐচ্ছিক ডিপেন্ডেন্সি অ্যারে গ্রহণ করে যা নির্বাহের ফ্রিকোয়েন্সি নিয়ন্ত্রণ করে।
মূল বিষয়
useEffect হল একটি হুক যা React 16.8-এ ফাংশনাল কম্পোনেন্টে সাইড ইফেক্ট সম্পাদনের জন্য যোগ করা হয়েছে। সাইড ইফেক্ট হল সেই অপারেশন যা UI রেন্ডারিংয়ের সাথে সরাসরি সম্পর্কিত নয়: API-তে HTTP অনুরোধ, ইভেন্ট সাবস্ক্রিপশন, টাইমার নিয়ে কাজ, DOM ম্যানিপুলেশন, লগিং এবং থার্ড-পার্টি লাইব্রেরির সাথে ইন্টিগ্রেশন।
হুক আসার আগে, এই সমস্ত অপারেশন ক্লাস কম্পোনেন্টের জীবনচক্র পদ্ধতিতে রাখতে হত: আরম্ভের জন্য componentDidMount, প্রপ্স পরিবর্তনে প্রতিক্রিয়ার জন্য componentDidUpdate, পরিষ্কারের জন্য componentWillUnmount। useEffect তিনটি পরিস্থিতিকেই একটি একক API-তে একীভূত করেছে, যেখানে ডিপেন্ডেন্সি অ্যারে নির্ধারণ করে কখন ইফেক্ট চালানো উচিত। এটি যুক্তিকে সরল করেছে এবং কোড পুনরাবৃত্তি কমিয়েছে, বিশেষ করে সাবস্ক্রিপশনের ক্ষেত্রে।
React DevTools Usage Survey (2024) অনুসারে, useEffect হল useState-এর পরে দ্বিতীয় সবচেয়ে জনপ্রিয় হুক, যা 89% React অ্যাপ্লিকেশনে ব্যবহৃত হয়। বেশিরভাগ ডেভেলপার এটি ডেটা আনা, বাহ্যিক সিস্টেমের সাথে সিঙ্ক্রোনাইজ করা এবং DOM ইভেন্ট সাবস্ক্রিপশন পরিচালনার জন্য ব্যবহার করেন।
import { useEffect } from 'react';
function UserProfile({ userId }) {
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => setUser(data));
}, [userId]);
}
useEffect রেন্ডারিং শেষ করার এবং DOM আপডেট করার পরে প্রেরিত ইফেক্ট ফাংশন চালায়। এটি রেন্ডার-টাইম গণনা থেকে একটি মূল পার্থক্য: ইফেক্ট রেন্ডারিং বন্ধ করে না, যা UX পারফরম্যান্সের জন্য গুরুত্বপূর্ণ। যদি ইফেক্টগুলি সিঙ্ক্রোনাসভাবে চালত, তাহলে ব্যবহারকারীরা ডেটা লোড হওয়ার সময় একটি জমে থাকা ইন্টারফেস দেখতে পেত।
একটি সাধারণ ইফেক্টের জীবনচক্র তিনটি পর্যায় নিয়ে গঠিত। কম্পোনেন্ট মাউন্ট করার সময়, React ইফেক্ট নির্বাহ করে। প্রতিটি আপডেটে, যদি অ্যারে থেকে কমপক্ষে একটি ডিপেন্ডেন্সি পরিবর্তিত হয়, React প্রথমে আগের ইফেক্টের ক্লিনআপ ফাংশন চালায়, তারপর নতুন ইফেক্ট। কম্পোনেন্ট আনমাউন্ট করার সময়, শুধুমাত্র ক্লিনআপ ফাংশন চলে।
React Team — useEffect RFC (2024) অনুসারে, useEffect-এর অভ্যন্তরীণ বাস্তবায়ন ফাইবার ট্রিতে সাইড ইফেক্ট কিউ ব্যবহার করে। পরিবর্তনগুলি কমিট করার পরে (কমিট ফেজ), React এই কিউ অতিক্রম করে এবং কম্পোনেন্টে যেই ক্রমে ঘোষণা করা হয়েছে সেই ক্রমে ইফেক্ট ফাংশন কল করে। প্রতিটি ফাইবার নোড সঠিক ক্লিনআপ এবং পুনরায় চালানোর জন্য আগের ইফেক্টের একটি রেফারেন্স সংরক্ষণ করে।
| পর্যায় | React-এর কাজ | কখন নির্বাহ হয় |
|---|---|---|
| মাউন্টিং | ইফেক্ট ফাংশন কল | প্রথম রেন্ডারের পরে |
| আপডেট | ক্লিনআপ → ইফেক্ট | যখন ডিপেন্ডেন্সি পরিবর্তিত হয় |
| আনমাউন্টিং | শুধুমাত্র ক্লিনআপ | যখন কম্পোনেন্ট সরানো হয় |
ডিপেন্ডেন্সি অ্যারে — useEffect-এর দ্বিতীয় আর্গুমেন্ট — নির্ধারণ করে কখন ইফেক্ট পুনরায় চালানো উচিত। React Object.is ব্যবহার করে অ্যারের প্রতিটি মানের সাথে আগের রেন্ডারের তুলনা করে। যদি কমপক্ষে একটি মান পরিবর্তিত হয়, ইফেক্ট আবার চলে। যদি অ্যারে খালি ([]) হয়, ইফেক্ট মাউন্ট করার পরে শুধুমাত্র একবার চলে।
সঠিক ডিপেন্ডেন্সি বেছে নেওয়া useEffect নিয়ে কাজ করার সবচেয়ে কঠিন অংশ। অ্যারেতে সেই সমস্ত ভেরিয়েবল এবং ফাংশন অন্তর্ভুক্ত হওয়া উচিত যা ইফেক্টের ভিতরে ব্যবহৃত হয় এবং রেন্ডারের মধ্যে পরিবর্তিত হতে পারে। একটি ডিপেন্ডেন্সি বাদ দিলে স্টেল ক্লোজার (stale closures) হয় — ইফেক্ট আগের রেন্ডার থেকে পুরানো মান দেখে। অপ্রয়োজনীয় ডিপেন্ডেন্সি অন্তর্ভুক্ত করলে অতিরিক্ত পুনরায় চালু এবং সম্ভাব্য বাগ হয়।
// ডিপেন্ডেন্সি নিয়ন্ত্রণ করে কি ইফেক্ট কব পুনরায় চলে
useEffect(() => {
document.title = `User: ${user.name}`;
}, [user.name]); // শুধুমাত্র যখন user.name পরিবর্তন হয় তখন পুনরায় চলুন
// eslint-disable-next-line react-hooks/exhaustive-deps
// আপনি যদি কোনো ডিপেন্ডেন্সি বাদ দেন, তবে আপনি পুরানো ডেটা পান
React eslint-plugin-react-hooks এক্সহস্টিভ-ডেপস নিয়মের সাথে সরবরাহ করে, যা স্বয়ংক্রিয়ভাবে ডিপেন্ডেন্সি অ্যারের সম্পূর্ণতা পরীক্ষা করে। Meta Engineering Blog (2024) অনুসারে, এই প্লাগইন সক্ষম করলে হুক-সম্পর্কিত বাগ 72% কমে যায়। কাস্টম লজিক সহ বিরল ক্ষেত্রে ছাড়া, সমস্ত এক্সহস্টিভ-ডেপস সতর্কতা মন্তব্যে চাপা দেওয়ার পরিবর্তে ঠিক করার পরামর্শ দেওয়া হয়।
যদি আপনি ডিপেন্ডেন্সি অ্যারে একেবারেই না দেন, তাহলে useEffect প্রতিটি রেন্ডারের পরে নির্বাহ হবে। এটি DOM সিঙ্ক্রোনাইজেশন বা লগিংয়ের জন্য উপযোগী হতে পারে, তবে বেশিরভাগ ক্ষেত্রে এটি একটি ভুল: ইফেক্ট খুব ঘন ঘন চলে, যা কর্মক্ষমতা হ্রাসের দিকে নিয়ে যায়। বেশিরভাগ ক্ষেত্রে, আপনার একটি খালি অ্যারে (মাউন্টে একবার) বা নির্দিষ্ট প্রপ্স/স্টেট সহ অ্যারে পাস করা উচিত।
খালি অ্যারে ([]) মানে ইফেক্ট কোনো মানের উপর নির্ভর করে না এবং কঠোরভাবে একবার নির্বাহ হয়। এটি ক্লাস কম্পোনেন্টে componentDidMount-এর সমতুল্য। তবে, মনে রাখবেন: যদি ইফেক্ট প্রপ্স বা স্টেট ব্যবহার করে যা ডিপেন্ডেন্সি অ্যারেতে তালিকাভুক্ত নয়, ইফেক্ট তাদের প্রাথমিক মান ব্যবহার করবে এবং কখনো আপডেট দেখবে না। একে স্টেল ক্যাপচার (stale capture) বলে এবং এটি প্রায়ই খুঁজে পাওয়া কঠিন বাগের উৎস।
| ডিপেন্ডেন্সি অ্যারে | আচরণ | ক্লাস সমতুল্য |
|---|---|---|
| কোনো আর্গুমেন্ট নেই | প্রতি রেন্ডারের পরে | componentDidUpdate |
| [] | মাউন্টে একবার | componentDidMount |
| [a, b] | যখন a বা b পরিবর্তিত হয় | ComponentWillReceiveProps অনুরূপ |
| ক্লিনআপ রিটার্ন | আনমাউন্টিং পরিচালনা | componentWillUnmount |
ক্লিনআপ ফাংশন হল একটি ফাংশন যা useEffect তার কলব্যাক থেকে ফিরিয়ে দিতে পারে। React এটি কম্পোনেন্ট আনমাউন্ট করার সময় এবং ডিপেন্ডেন্সি পরিবর্তিত হলে ইফেক্ট পুনরায় চালানোর আগে কল করে। সাবস্ক্রিপশন, টাইমার, অনুরোধ এবং যে কোনো রিসোর্স বাতিল করার জন্য যা মুক্ত করতে হবে তার জন্য ক্লিনআপ প্রয়োজনীয়।
একটি সাধারণ উদাহরণ হল WebSocket সাবস্ক্রিপশন। মাউন্ট করার সময়, একটি সংযোগ তৈরি হয়; ডিপেন্ডেন্সি আপডেটে, এটি পুনরায় তৈরি হয় (ক্লিনআপ পুরানোটিকে বন্ধ করে, ইফেক্ট নতুনটি খোলে); আনমাউন্ট করার সময়, এটি বন্ধ হয়। ক্লিনআপ ছাড়া, কম্পোনেন্টের প্রতিটি পুনঃমাউন্ট একটি নতুন WebSocket সংযোগ তৈরি করবে, যা মেমরি লিক এবং একাধিক সংযোগের দিকে নিয়ে যাবে।
useEffect(() => {
const socket = new WebSocket('wss://api.example.com');
socket.onmessage = event => setData(event.data);
// ক্লিনআপ ফাংশন — আনমাউন্টে এবং পুনরায় চালানোর আগে চলে
return () => {
socket.close();
};
}, []);
React Documentation (2025) অনুসারে, AbortController হল ক্লিনআপে fetch অনুরোধ বাতিল করার আধুনিক পদ্ধতি। যদি ইফেক্ট একটি HTTP অনুরোধ করে এবং কম্পোনেন্ট এটি শেষ হওয়ার আগে আনমাউন্ট হয়, অনুরোধ চলতে থাকে এবং আনমাউন্টের পরে setState একটি ত্রুটি সৃষ্টি করে। ইফেক্টের ভিতরে AbortController তৈরি করুন এবং অনুরোধ বাতিল করতে ক্লিনআপে controller.abort() কল করুন।
সবচেয়ে সাধারণ ভুল হল ডিপেন্ডেন্সি বাদ দেওয়া। উদাহরণস্বরূপ, ইফেক্ট প্রপ userId ব্যবহার করে, কিন্তু ডিপেন্ডেন্সি অ্যারেটি খালি। ফলস্বরূপ, ইফেক্ট প্রাথমিক userId মান নিয়ে একবার চলে এবং কখনো তার পরিবর্তনে সাড়া দেয় না। ডেভেলপার দেখেন যে কম্পোনেন্ট একটি নতুন userId পাচ্ছে, কিন্তু ডেটা আপডেট হয় না। এক্সহস্টিভ-ডেপস নিয়ম সহ eslint-plugin-react-hooks স্বয়ংক্রিয়ভাবে এই ধরনের বাগ সনাক্ত করে।
// ❌ রেস কন্ডিশন — কোনো বাতিল নেই
useEffect(() => {
fetch(`/api/user/${userId}`).then(res => setUser(res));
}, [userId]);
// ✅ AbortController দিয়ে সমাধান
useEffect(() => {
const controller = new AbortController();
fetch(`/api/user/${userId}`, { signal: controller.signal })
.then(res => setUser(res));
return () => controller.abort();
}, [userId]);
অন্তহীন লুপ সমস্যা সমাধানের জন্য, useEffect-এ এমন যুক্তি রাখা এড়িয়ে চলুন যা আগের স্টেটের উপর ভিত্তি করে স্টেট আপডেট করে। setState-এর ফাংশনাল ফর্ম ব্যবহার করুন বা গণনা ইফেক্টের বাইরে সরান। যদি ইফেক্ট স্টোরেজ বা ব্রাউজার ইভেন্টে সাবস্ক্রাইব করে, তাহলে নিশ্চিত করুন যে লিসেনার ইনস্ট্যান্স একবার তৈরি হয়েছে, প্রতি রেন্ডারে নয়।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
সরাসরি — না, কারণ useEffect একটি সিঙ্ক্রোনাস ফাংশন বা undefined ফিরিয়ে আশা করে। যদি কলব্যাকটি async হিসাবে ঘোষণা করা হয়, এটি একটি Promise ফেরত দেয় যা React উপেক্ষা করে এবং ক্লিনআপ মেকানিজম কাজ করা বন্ধ করে দেয়। সমাধান: ইফেক্টের ভিতরে একটি async ফাংশন কল করুন: useEffect(() => { async function load() { ... }; load(); }, [])।
কোনো সীমা নেই। React অসম্পর্কিত যুক্তি পৃথক useEffect-এ আলাদা করার পরামর্শ দেয়, এমনকি যদি তাদের একই ডিপেন্ডেন্সি অ্যারে থাকে। প্রতিটি ইফেক্ট একটি স্পষ্টভাবে সংজ্ঞায়িত সাইড টাস্কের জন্য দায়ী হওয়া উচিত: একটি সাবস্ক্রিপশনের জন্য, অন্যটি ডেটা লোড করার জন্য, তৃতীয়টি ট্যাব শিরোনাম সিঙ্ক্রোনাইজ করার জন্য। এটি বোঝা এবং ডিবাগিং সহজ করে।
React Strict Mode (শুধুমাত্র ডেভেলপমেন্ট মোড)-এ, সমস্ত ইফেক্ট মাউন্ট, আনমাউন্ট এবং আবার মাউন্ট করা হয়। এটি একটি বৈশিষ্ট্য, বাগ নয় — React পরীক্ষা করে যে ক্লিনআপ সঠিকভাবে কাজ করে কিনা। যদি আনমাউন্ট এবং পুনরায় মাউন্ট করার পরে ইফেক্ট ভুল আচরণ করে (যেমন, ডুপ্লিকেট সাবস্ক্রিপশন), আপনার ক্লিনআপ অসম্পূর্ণ। প্রোডাকশনে, ইফেক্ট একবার চালু হয়।
AbortController ব্যবহার করুন। ইফেক্টের ভিতরে একটি controller তৈরি করুন, controller.signal fetch-এ প্রেরণ করুন এবং ক্লিনআপে controller.abort() কল করুন। যদি কম্পোনেন্ট অনুরোধ শেষ হওয়ার আগে আনমাউন্ট হয়, fetch বাতিল হয়ে যায় এবং setState কল করা হবে না। এটি রেস কন্ডিশন এবং “Can't perform a React state update on an unmounted component” ত্রুটি প্রতিরোধ করে।
useEffect ব্যতিক্রম ছাড়া প্রতিটি রেন্ডারের পরে চালু হবে। এর মানে হল ইফেক্টের ভিতরে যেকোনো setState একটি নতুন রেন্ডার → নতুন ইফেক্ট → অন্তহীন লুপ সৃষ্টি করবে। অনুশীলনে, ডিপেন্ডেন্সি অ্যারে ছাড়া একটি ইফেক্ট প্রায় সবসময়ই একটি ভুল। ব্যতিক্রম হল লগিং বা বাহ্যিক সিস্টেমের সাথে সিঙ্ক্রোনাইজেশন যেখানে প্রতিটি রেন্ডারের সিঙ্ক্রোনাইজেশন প্রয়োজন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন