useEffect: یہ کیا ہے، سائیڈ ایفیکٹس ہک اور React میں لائف سائیکل

مصنف: IT Sectr اشاعت: 2026-07-04 مطالعے کا وقت: 9 منٹ

useEffect ایک React ہک ہے جو آپ کو فنکشنل کمپوننٹس میں سائیڈ ایفیکٹس انجام دینے کی اجازت دیتا ہے، کلاس کمپوننٹس کے لائف سائیکل طریقوں کو تبدیل کرتا ہے: componentDidMount، componentDidUpdate اور componentWillUnmount۔ React Documentation (2025) کے مطابق، useEffect اس وقت عمل میں آتا ہے جب React DOM میں تبدیلیاں کمٹ کر چکا ہوتا ہے، جو حقیقی DOM درخت تک رسائی کو یقینی بناتا ہے۔ ہک ایک ایفیکٹ فنکشن اور ایک اختیاری ڈیپنڈنسی اری قبول کرتا ہے جو عمل درآمد کی تعدد کو کنٹرول کرتا ہے۔

اہم نکات

  • useEffect کمپوننٹ رینڈر کے بعد سائیڈ ایفیکٹس انجام دینے کے لیے ایک ہک ہے۔
  • ڈیپنڈنسی اری کنٹرول کرتی ہے کہ ایفیکٹ کب دوبارہ چلے؛ خالی اری = ایک بار۔
  • صفائی (cleanup) — ایفیکٹ سے صفائی کا فنکشن ان ماؤنٹ کرنے پر اور دوبارہ چلانے سے پہلے کال کیا جاتا ہے۔
  • لائف سائیکل — componentDidMount، componentDidUpdate اور componentWillUnmount کو تبدیل کرتا ہے۔
  • عمل درآمد کا ترتیب — ایفیکٹس DOM میں تبدیلیاں کمٹ ہونے کے بعد چلتے ہیں۔

React میں useEffect کیا ہے

useEffect ایک ہک ہے جو React 16.8 میں فنکشنل کمپوننٹس میں سائیڈ ایفیکٹس انجام دینے کے لیے شامل کیا گیا تھا۔ سائیڈ ایفیکٹس وہ آپریشنز ہیں جو UI رینڈرنگ سے براہ راست متعلق نہیں ہیں: APIs کو HTTP درخواستیں، ایونٹ سبسکرپشنز، ٹائمرز کے ساتھ کام، DOM میں ہیرا پھیری، لاگنگ اور تیسرے فریق کی لائبریریوں کے ساتھ انضمام۔

ہکس سے پہلے، ان تمام آپریشنز کو کلاس کمپوننٹس کے لائف سائیکل طریقوں میں رکھنا پڑتا تھا: ابتدا کے لیے componentDidMount، props تبدیلیوں پر ردعمل کے لیے componentDidUpdate، صفائی کے لیے componentWillUnmount۔ useEffect نے تینوں منظرناموں کو ایک واحد API میں یکجا کیا، جہاں ڈیپنڈنسی اری تعین کرتی ہے کہ ایفیکٹ کب چلنا چاہیے۔ اس نے منطق کو آسان بنایا اور کوڈ کے دہراؤ کو کم کیا، خاص طور پر سبسکرپشن منظرناموں میں۔

React DevTools Usage Survey (2024) کے مطابق، useEffect useState کے بعد دوسرا سب سے مقبول ہک ہے، جو 89% React ایپلیکیشنز میں استعمال ہوتا ہے۔ زیادہ تر ڈیولپرز اسے ڈیٹا لانے، بیرونی سسٹمز کے ساتھ ہم آہنگی کرنے اور DOM ایونٹ سبسکرپشنز کو منظم کرنے کے لیے استعمال کرتے ہیں۔

jsx
import { useEffect } from 'react';

function UserProfile({ userId }) {
    useEffect(() => {
        fetch(`/api/users/${userId}`)
            .then(res => res.json())
            .then(data => setUser(data));
    }, [userId]);
}

useEffect کیسے کام کرتا ہے: ایفیکٹ لائف سائیکل

useEffect رینڈرنگ مکمل کرنے اور DOM کو اپ ڈیٹ کرنے کے بعد دیے گئے ایفیکٹ فنکشن کو چلاتا ہے۔ یہ رینڈر ٹائم حساب سے ایک اہم فرق ہے: ایفیکٹ رینڈرنگ کو مسدود نہیں کرتا، جو UX کارکردگی کے لیے اہم ہے۔ اگر ایفیکٹس ہم وقت (synchronous) طور پر چلتے، تو صارف ڈیٹا لوڈ ہونے کے دوران ایک منجمد انٹرفیس دیکھتا۔

ایک عام ایفیکٹ کا لائف سائیکل تین مراحل پر مشتمل ہوتا ہے۔ کمپوننٹ ماؤنٹ ہونے پر، React ایفیکٹ کو انجام دیتا ہے۔ ہر اپ ڈیٹ پر، اگر اری میں کم از کم ایک ڈیپنڈنسی تبدیل ہوئی ہے، تو React پہلے پچھلے ایفیکٹ کا صفائی فنکشن چلاتا ہے، پھر نیا ایفیکٹ۔ کمپوننٹ ان ماؤنٹ ہونے پر، صرف صفائی کا فنکشن چلتا ہے۔

React Team — useEffect RFC (2024) کے مطابق، useEffect کا داخلی نفاذ فائبر ٹری میں سائیڈ ایفیکٹ قطار استعمال کرتا ہے۔ تبدیلیاں کمٹ کرنے کے بعد (کمٹ فیز)، React اس قطار میں چلتا ہے اور ایفیکٹ فنکشنز کو اس ترتیب میں کال کرتا ہے جس میں وہ کمپوننٹ میں اعلان کیے گئے تھے۔ ہر فائبر نوڈ پچھلے ایفیکٹ کا حوالہ درست صفائی اور دوبارہ چلانے کے لیے محفوظ کرتا ہے۔

مرحلہReact کا عملکب عمل میں آتا ہے
ماؤنٹنگایفیکٹ فنکشن کال کریںپہلے رینڈر کے بعد
اپ ڈیٹصفائی → ایفیکٹجب ڈیپنڈنسی تبدیل ہوتی ہیں
ان ماؤنٹنگصرف صفائیجب کمپوننٹ ہٹایا جاتا ہے

useEffect ڈیپنڈنسی اری

ڈیپنڈنسی اری — useEffect کا دوسرا دلیل — یہ تعین کرتی ہے کہ ایفیکٹ کب دوبارہ چلنا چاہیے۔ React Object.is کا استعمال کرتے ہوئے اری میں ہر قدر کا پچھلے رینڈر سے موازنہ کرتا ہے۔ اگر کم از کم ایک قدر تبدیل ہوئی ہے، تو ایفیکٹ دوبارہ چلتا ہے۔ اگر اری خالی ([]) ہے، تو ایفیکٹ ماؤنٹنگ کے بعد صرف ایک بار چلتا ہے۔

صحیح ڈیپنڈنسی کا انتخاب کرنا useEffect کے ساتھ کام کرنے کا سب سے مشکل حصہ ہے۔ اری میں ان تمام متغیرات اور فنکشنز کو شامل ہونا چاہیے جو ایفیکٹ کے اندر استعمال ہوتے ہیں اور رینڈرز کے درمیان تبدیل ہو سکتے ہیں۔ ڈیپنڈنسی چھوڑنے سے پرانے بندش (stale closure) ہوتے ہیں — ایفیکٹ پچھلے رینڈر سے پرانی قدر دیکھتا ہے۔ غیر ضروری ڈیپنڈنسی شامل کرنے سے ضرورت سے زیادہ دوبارہ چلنا اور ممکنہ بگز ہوتے ہیں۔

jsx
// ڈیپنڈنسیز کنٹرول کرتی ہیں کہ ایفیکٹ کب دوبارہ چلے
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 بغیر ڈیپنڈنسی اور خالی اری کے ساتھ

اگر آپ ڈیپنڈنسی اری بالکل نہیں دیتے ہیں، تو useEffect ہر رینڈر کے بعد عمل میں آئے گا۔ یہ DOM ہم آہنگی یا لاگنگ کے لیے مفید ہو سکتا ہے، لیکن اکثر یہ ایک غلطی ہے: ایفیکٹ بہت بار چلتا ہے، جس سے کارکردگی میں کمی آتی ہے۔ زیادہ تر معاملات میں، آپ کو ایک خالی اری (ماؤنٹ پر ایک بار) یا مخصوص props/state والی اری دینی چاہیے۔

خالی اری ([]) کا مطلب ہے کہ ایفیکٹ کسی بھی قدر پر منحصر نہیں ہے اور سختی سے ایک بار عمل میں آتا ہے۔ یہ کلاس کمپوننٹس میں componentDidMount کے برابر ہے۔ تاہم، یاد رکھیں: اگر ایفیکٹ props یا state استعمال کرتا ہے جو ڈیپنڈنسی اری میں درج نہیں ہیں، تو ایفیکٹ ان کی ابتدائی قدریں استعمال کرے گا اور اپ ڈیٹس کبھی نہیں دیکھے گا۔ اسے پرانا حصول (stale capture) کہا جاتا ہے اور یہ اکثر مشکل سے ملنے والے بگز کا ذریعہ ہوتا ہے۔

ڈیپنڈنسی اریسلوککلاس مساوی
بغیر دلیلہر رینڈر کے بعدcomponentDidUpdate
[]ماؤنٹ پر ایک بارcomponentDidMount
[a, b]جب a یا b تبدیل ہوتا ہےComponentWillReceiveProps مشابہ
return cleanupان ماؤنٹنگ کو منظم کریںcomponentWillUnmount

useEffect میں ایفیکٹس کی صفائی

صفائی کا فنکشن ایک فنکشن ہے جسے useEffect اپنے کال بیک سے واپس کر سکتا ہے۔ React اسے کمپوننٹ ان ماؤنٹ ہونے پر اور ڈیپنڈنسی تبدیل ہونے پر ایفیکٹ کو دوبارہ چلانے سے پہلے کال کرتا ہے۔ صفائی سبسکرپشنز، ٹائمرز، درخواستوں اور کسی بھی وسائل کو منسوخ کرنے کے لیے ضروری ہے جسے آزاد کیا جانا چاہیے۔

ایک عام مثال WebSocket سبسکرپشن ہے۔ ماؤنٹ پر، ایک کنکشن بنایا جاتا ہے؛ ڈیپنڈنسی اپ ڈیٹ پر، اسے دوبارہ بنایا جاتا ہے (صفائی پرانے کو بند کرتی ہے، ایفیکٹ نیا کھولتا ہے)؛ ان ماؤنٹ پر، یہ بند ہو جاتا ہے۔ صفائی کے بغیر، کمپوننٹ کا ہر دوبارہ ماؤنٹ ایک نیا WebSocket کنکشن بنائے گا، جو میموری لیک اور متعدد کنکشنز کا باعث بنے گا۔

jsx
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() کال کریں۔

useEffect کے ساتھ عام غلطیاں

سب سے عام غلطی ڈیپنڈنسی چھوڑنا ہے۔ مثال کے طور پر، ایفیکٹ userId prop استعمال کرتا ہے، لیکن ڈیپنڈنسی اری خالی ہے۔ نتیجے کے طور پر، ایفیکٹ ابتدائی userId قدر کے ساتھ ایک بار چلتا ہے اور اس کی تبدیلیوں پر کبھی رد عمل نہیں دکھاتا۔ ڈیولپر دیکھتا ہے کہ کمپوننٹ ایک نیا userId وصول کر رہا ہے، لیکن ڈیٹا اپ ڈیٹ نہیں ہوتا۔ exhaustive-deps اصول کے ساتھ eslint-plugin-react-hooks ایسے بگز خود بخود دریافت کرتا ہے۔

  • لامتناہی لوپ — ایفیکٹ کے اندر state کو اپ ڈیٹ کرنا، جس سے دوبارہ رینڈر ہوتا ہے جو ایفیکٹ کو دوبارہ چلاتا ہے۔ حل: ڈیپنڈنسی اری چیک کریں یا سیٹر کی فنکشنل شکل استعمال کریں۔
  • ریس کنڈیشن — اگر userId تیزی سے تبدیل ہوتا ہے، تو پہلے userId کی درخواست دوسرے کے بعد مکمل ہو سکتی ہے، غلط ڈیٹا دکھاتی ہے۔ حل: منسوخ شدہ پرچم یا AbortController استعمال کریں۔
  • ضرورت سے زیادہ ایفیکٹس — غیر متعلقہ منطق کو ایک useEffect میں یکجا کرنا۔ React متعدد ایفیکٹس میں منطق تقسیم کرنے کی سفارش کرتا ہے، چاہے ان کے پاس ایک ہی ڈیپنڈنسی اری ہو۔
  • بھولی ہوئی صفائی — ایونٹس سے ان سبسکرائب نہ کرنا، ٹائمرز صاف نہ کرنا یا درخواستیں منسوخ نہ کرنا میموری لیک اور ان ماؤنٹ کے بعد setState خرابیوں کا باعث بنتا ہے۔
jsx
// ❌ ریس کنڈیشن — کوئی منسوخی نہیں
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 کے اندر async/await استعمال کیا جا سکتا ہے؟

براہ راست — نہیں، کیونکہ useEffect ایک ہم وقت فنکشن یا undefined واپس کرنے کی توقع رکھتا ہے۔ اگر کال بیک کو async کے طور پر اعلان کیا جاتا ہے، تو یہ ایک Promise لوٹاتا ہے جسے React نظر انداز کرتا ہے، اور صفائی کا طریقہ کار کام کرنا بند کر دیتا ہے۔ حل: ایفیکٹ کے اندر ایک async فنکشن کال کریں: useEffect(() => { async function load() { ... }; load(); }, [])۔

ایک کمپوننٹ میں کتنے useEffect ہو سکتے ہیں؟

کوئی حد نہیں ہے۔ React غیر متعلقہ منطق کو علیحدہ useEffect میں الگ کرنے کی سفارش کرتا ہے، چاہے ان کے پاس ایک ہی ڈیپنڈنسی اری ہو۔ ہر ایفیکٹ کو ایک واضح طور پر متعین ضمنی کام کے لیے ذمہ دار ہونا چاہیے: ایک سبسکرپشن کے لیے، دوسرا ڈیٹا لوڈ کرنے کے لیے، تیسرا ٹیب کے عنوان کو ہم آہنگ کرنے کے لیے۔ یہ سمجھنے اور ڈیبگ کرنے کو آسان بناتا ہے۔

StrictMode میں useEffect دو بار کیوں چلتا ہے؟

React Strict Mode (صرف ڈیولپمنٹ موڈ) میں، تمام ایفیکٹس ماؤنٹ، ان ماؤنٹ اور دوبارہ ماؤنٹ کیے جاتے ہیں۔ یہ ایک خصوصیت ہے، بگ نہیں — React چیک کرتا ہے کہ صفائی صحیح طریقے سے کام کرتی ہے یا نہیں۔ اگر ان ماؤنٹ اور دوبارہ ماؤنٹ کرنے کے بعد ایفیکٹ غلط رویہ دکھاتا ہے (مثلاً، ڈپلیکیٹ سبسکرپشنز)، تو آپ کی صفائی نامکمل ہے۔ پروڈکشن میں، ایفیکٹ ایک بار چلتا ہے۔

useEffect میں fetch درخواست کو کیسے منسوخ کریں؟

AbortController استعمال کریں۔ ایفیکٹ کے اندر ایک controller بنائیں، controller.signal کو fetch میں دیں، اور صفائی میں controller.abort() کال کریں۔ اگر درخواست مکمل ہونے سے پہلے کمپوننٹ ان ماؤنٹ ہو جاتا ہے، تو fetch منسوخ ہو جاتا ہے اور setState کال نہیں ہوگا۔ یہ ریس کنڈیشن اور “Can't perform a React state update on an unmounted component” خرابی کو روکتا ہے۔

اگر میں ڈیپنڈنسی اری نہیں دیتا تو کیا ہوتا ہے؟

useEffect بغیر کسی استثنا کے ہر رینڈر کے بعد چلے گا۔ اس کا مطلب ہے کہ ایفیکٹ کے اندر کوئی بھی setState نیا رینڈر → نیا ایفیکٹ → لامتناہی لوپ کا سبب بنے گا۔ عملی طور پر، ڈیپنڈنسی اری کے بغیر ایفیکٹ تقریباً ہمیشہ ایک غلطی ہے۔ مستثنیات لاگنگ یا بیرونی نظام کے ساتھ ہم آہنگی ہیں جہاں ہر رینڈر کو ہم آہنگی کی ضرورت ہوتی ہے۔

خلاصہ

  • useEffect DOM کمٹ کے بعد سائیڈ ایفیکٹس انجام دینے کے لیے ایک ہک ہے، جو componentDidMount، componentDidUpdate اور componentWillUnmount کو تبدیل کرتا ہے۔
  • ڈیپنڈنسی اری ایفیکٹ کے دوبارہ چلنے کو کنٹرول کرتی ہے؛ خالی اری = ایک بار، ڈیپنڈنسی چھوڑنا = پرانی بندش۔
  • صفائی سبسکرپشنز، ٹائمرز اور درخواستوں کے لیے لازمی ہے؛ اس کے بغیر میموری لیک ہوتی ہے۔
  • AbortController ریس کنڈیشن کو روکتے ہوئے، useEffect کے اندر fetch درخواستوں کو منسوخ کرنے کا صحیح طریقہ ہے۔
  • StrictMode صفائی کی درستگی کی تصدیق کے لیے ڈیولپمنٹ موڈ میں ایفیکٹ کو دو بار ماؤنٹ کرتا ہے۔
  • ایفیکٹس کو الگ کریں — ہر useEffect، ڈیپنڈنسی ملنے پر بھی، ایک کام سنبھالتا ہے۔
  • eslint-plugin-react-hooks خود بخود ڈیپنڈنسی اری کی مکمل جانچ کرتا ہے، بگز کو 72% کم کرتا ہے۔

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں