useEffect ایک React ہک ہے جو آپ کو فنکشنل کمپوننٹس میں سائیڈ ایفیکٹس انجام دینے کی اجازت دیتا ہے، کلاس کمپوننٹس کے لائف سائیکل طریقوں کو تبدیل کرتا ہے: componentDidMount، componentDidUpdate اور componentWillUnmount۔ React Documentation (2025) کے مطابق، useEffect اس وقت عمل میں آتا ہے جب React DOM میں تبدیلیاں کمٹ کر چکا ہوتا ہے، جو حقیقی DOM درخت تک رسائی کو یقینی بناتا ہے۔ ہک ایک ایفیکٹ فنکشن اور ایک اختیاری ڈیپنڈنسی اری قبول کرتا ہے جو عمل درآمد کی تعدد کو کنٹرول کرتا ہے۔
اہم نکات
useEffect ایک ہک ہے جو React 16.8 میں فنکشنل کمپوننٹس میں سائیڈ ایفیکٹس انجام دینے کے لیے شامل کیا گیا تھا۔ سائیڈ ایفیکٹس وہ آپریشنز ہیں جو UI رینڈرنگ سے براہ راست متعلق نہیں ہیں: APIs کو HTTP درخواستیں، ایونٹ سبسکرپشنز، ٹائمرز کے ساتھ کام، DOM میں ہیرا پھیری، لاگنگ اور تیسرے فریق کی لائبریریوں کے ساتھ انضمام۔
ہکس سے پہلے، ان تمام آپریشنز کو کلاس کمپوننٹس کے لائف سائیکل طریقوں میں رکھنا پڑتا تھا: ابتدا کے لیے componentDidMount، props تبدیلیوں پر ردعمل کے لیے 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 کارکردگی کے لیے اہم ہے۔ اگر ایفیکٹس ہم وقت (synchronous) طور پر چلتے، تو صارف ڈیٹا لوڈ ہونے کے دوران ایک منجمد انٹرفیس دیکھتا۔
ایک عام ایفیکٹ کا لائف سائیکل تین مراحل پر مشتمل ہوتا ہے۔ کمپوننٹ ماؤنٹ ہونے پر، React ایفیکٹ کو انجام دیتا ہے۔ ہر اپ ڈیٹ پر، اگر اری میں کم از کم ایک ڈیپنڈنسی تبدیل ہوئی ہے، تو React پہلے پچھلے ایفیکٹ کا صفائی فنکشن چلاتا ہے، پھر نیا ایفیکٹ۔ کمپوننٹ ان ماؤنٹ ہونے پر، صرف صفائی کا فنکشن چلتا ہے۔
React Team — useEffect RFC (2024) کے مطابق، useEffect کا داخلی نفاذ فائبر ٹری میں سائیڈ ایفیکٹ قطار استعمال کرتا ہے۔ تبدیلیاں کمٹ کرنے کے بعد (کمٹ فیز)، React اس قطار میں چلتا ہے اور ایفیکٹ فنکشنز کو اس ترتیب میں کال کرتا ہے جس میں وہ کمپوننٹ میں اعلان کیے گئے تھے۔ ہر فائبر نوڈ پچھلے ایفیکٹ کا حوالہ درست صفائی اور دوبارہ چلانے کے لیے محفوظ کرتا ہے۔
| مرحلہ | React کا عمل | کب عمل میں آتا ہے |
|---|---|---|
| ماؤنٹنگ | ایفیکٹ فنکشن کال کریں | پہلے رینڈر کے بعد |
| اپ ڈیٹ | صفائی → ایفیکٹ | جب ڈیپنڈنسی تبدیل ہوتی ہیں |
| ان ماؤنٹنگ | صرف صفائی | جب کمپوننٹ ہٹایا جاتا ہے |
ڈیپنڈنسی اری — useEffect کا دوسرا دلیل — یہ تعین کرتی ہے کہ ایفیکٹ کب دوبارہ چلنا چاہیے۔ React Object.is کا استعمال کرتے ہوئے اری میں ہر قدر کا پچھلے رینڈر سے موازنہ کرتا ہے۔ اگر کم از کم ایک قدر تبدیل ہوئی ہے، تو ایفیکٹ دوبارہ چلتا ہے۔ اگر اری خالی ([]) ہے، تو ایفیکٹ ماؤنٹنگ کے بعد صرف ایک بار چلتا ہے۔
صحیح ڈیپنڈنسی کا انتخاب کرنا useEffect کے ساتھ کام کرنے کا سب سے مشکل حصہ ہے۔ اری میں ان تمام متغیرات اور فنکشنز کو شامل ہونا چاہیے جو ایفیکٹ کے اندر استعمال ہوتے ہیں اور رینڈرز کے درمیان تبدیل ہو سکتے ہیں۔ ڈیپنڈنسی چھوڑنے سے پرانے بندش (stale closure) ہوتے ہیں — ایفیکٹ پچھلے رینڈر سے پرانی قدر دیکھتا ہے۔ غیر ضروری ڈیپنڈنسی شامل کرنے سے ضرورت سے زیادہ دوبارہ چلنا اور ممکنہ بگز ہوتے ہیں۔
// ڈیپنڈنسیز کنٹرول کرتی ہیں کہ ایفیکٹ کب دوبارہ چلے
useEffect(() => {
document.title = `User: ${user.name}`;
}, [user.name]); // صرف اس وقت دوبارہ چلائیں جب user.name بدلتا ہے
// eslint-disable-next-line react-hooks/exhaustive-deps
// اگر آپ کوئی ڈیپنڈنسی چھوڑ دیتے ہیں، تو آپکو پرانا ڈیٹا ملتا ہے
React eslint-plugin-react-hooks کو exhaustive-deps اصول کے ساتھ فراہم کرتا ہے، جو خود بخود ڈیپنڈنسی اری کی مکمل جانچ کرتا ہے۔ Meta Engineering Blog (2024) کے مطابق، اس پلگ ان کو فعال کرنے سے ہک سے متعلق بگز 72% کم ہو جاتے ہیں۔ کسٹم منطق والے نایاب معاملات کو چھوڑ کر، تمام exhaustive-deps انتباہات کو تبصرے سے دبانے کے بجائے ٹھیک کرنے کی سفارش کی جاتی ہے۔
اگر آپ ڈیپنڈنسی اری بالکل نہیں دیتے ہیں، تو useEffect ہر رینڈر کے بعد عمل میں آئے گا۔ یہ DOM ہم آہنگی یا لاگنگ کے لیے مفید ہو سکتا ہے، لیکن اکثر یہ ایک غلطی ہے: ایفیکٹ بہت بار چلتا ہے، جس سے کارکردگی میں کمی آتی ہے۔ زیادہ تر معاملات میں، آپ کو ایک خالی اری (ماؤنٹ پر ایک بار) یا مخصوص props/state والی اری دینی چاہیے۔
خالی اری ([]) کا مطلب ہے کہ ایفیکٹ کسی بھی قدر پر منحصر نہیں ہے اور سختی سے ایک بار عمل میں آتا ہے۔ یہ کلاس کمپوننٹس میں componentDidMount کے برابر ہے۔ تاہم، یاد رکھیں: اگر ایفیکٹ props یا state استعمال کرتا ہے جو ڈیپنڈنسی اری میں درج نہیں ہیں، تو ایفیکٹ ان کی ابتدائی قدریں استعمال کرے گا اور اپ ڈیٹس کبھی نہیں دیکھے گا۔ اسے پرانا حصول (stale capture) کہا جاتا ہے اور یہ اکثر مشکل سے ملنے والے بگز کا ذریعہ ہوتا ہے۔
| ڈیپنڈنسی اری | سلوک | کلاس مساوی |
|---|---|---|
| بغیر دلیل | ہر رینڈر کے بعد | componentDidUpdate |
| [] | ماؤنٹ پر ایک بار | componentDidMount |
| [a, b] | جب a یا b تبدیل ہوتا ہے | ComponentWillReceiveProps مشابہ |
| return cleanup | ان ماؤنٹنگ کو منظم کریں | 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 prop استعمال کرتا ہے، لیکن ڈیپنڈنسی اری خالی ہے۔ نتیجے کے طور پر، ایفیکٹ ابتدائی userId قدر کے ساتھ ایک بار چلتا ہے اور اس کی تبدیلیوں پر کبھی رد عمل نہیں دکھاتا۔ ڈیولپر دیکھتا ہے کہ کمپوننٹ ایک نیا userId وصول کر رہا ہے، لیکن ڈیٹا اپ ڈیٹ نہیں ہوتا۔ exhaustive-deps اصول کے ساتھ 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 میں ایسی منطق ڈالنے سے گریز کریں جو پچھلی state کی بنیاد پر state کو اپ ڈیٹ کرتی ہے۔ 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 ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں