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, प्रॉप्स परिवर्तनों पर प्रतिक्रिया के लिए 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 प्रदर्शन के लिए महत्वपूर्ण है। यदि इफेक्ट्स सिंक्रोनस रूप से चलते, तो उपयोगकर्ता डेटा लोड होने के दौरान एक जमी हुई इंटरफ़ेस देखता।

एक सामान्य इफेक्ट का जीवनचक्र तीन चरणों में होता है। कंपोनेंट माउंट होने पर, React इफेक्ट निष्पादित करता है। प्रत्येक अपडेट पर, यदि ऐरे से कम से कम एक डिपेंडेंसी बदल गई है, तो React पहले पिछले इफेक्ट का क्लीनअप फ़ंक्शन चलाता है, फिर नया इफेक्ट। कंपोनेंट अनमाउंट होने पर, केवल क्लीनअप फ़ंक्शन चलता है।

React Team — useEffect RFC (2024) के अनुसार, useEffect का आंतरिक कार्यान्वयन फाइबर ट्री में साइड इफेक्ट क्यू का उपयोग करता है। परिवर्तनों को कमिट करने (कमिट फेज़) के बाद, React इस क्यू में चलता है और इफेक्ट फ़ंक्शन को उस क्रम में कॉल करता है जिसमें वे कंपोनेंट में घोषित किए गए थे। प्रत्येक फाइबर नोड सही सफाई और पुनः चलाने के लिए पिछले इफेक्ट का संदर्भ संग्रहीत करता है।

चरणReact कार्रवाईकब निष्पादित होता है
माउंटिंगइफेक्ट फ़ंक्शन कॉल करेंपहले रेंडर के बाद
अपडेटक्लीनअप → इफेक्टजब डिपेंडेंसी बदलती हैं
अनमाउंटिंगकेवल क्लीनअपजब कंपोनेंट हटाया जाता है

useEffect डिपेंडेंसी ऐरे

डिपेंडेंसी ऐरे — useEffect का दूसरा तर्क — यह निर्धारित करता है कि इफेक्ट कब फिर से चलना चाहिए। React Object.is का उपयोग करके ऐरे में प्रत्येक मान की तुलना पिछले रेंडर से करता है। यदि कम से कम एक मान बदल गया है, तो इफेक्ट फिर से चलता है। यदि ऐरे खाली ([]) है, तो इफेक्ट माउंटिंग के बाद केवल एक बार चलता है।

सही डिपेंडेंसी चुनना useEffect के साथ काम करने का सबसे कठिन हिस्सा है। ऐरे में उन सभी वेरिएबल्स और फ़ंक्शन को शामिल होना चाहिए जो इफेक्ट के अंदर उपयोग किए जाते हैं और रेंडर के बीच बदल सकते हैं। डिपेंडेंसी छोड़ने से स्टेल क्लोज़र (stale closures) होते हैं — इफेक्ट पिछले रेंडर से पुराना मान देखता है। अनावश्यक डिपेंडेंसी शामिल करने से अत्यधिक पुनर्चालन और संभावित बग होते हैं।

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 सिंक्रनाइज़ेशन या लॉगिंग के लिए उपयोगी हो सकता है, लेकिन अक्सर यह एक गलती है: इफेक्ट बहुत बार चलता है, जिससे प्रदर्शन हानि होती है। अधिकांश मामलों में, आपको एक खाली ऐरे (माउंट पर एक बार) या विशिष्ट प्रॉप्स/स्टेट वाला ऐरे पास करना चाहिए।

खाली ऐरे ([]) का अर्थ है कि इफेक्ट किसी भी मान पर निर्भर नहीं करता है और सख्ती से एक बार निष्पादित होता है। यह क्लास कंपोनेंट्स में componentDidMount के समतुल्य है। हालांकि, ध्यान रखें: यदि इफेक्ट प्रॉप्स या स्टेट का उपयोग करता है जो डिपेंडेंसी ऐरे में सूचीबद्ध नहीं हैं, तो इफेक्ट उनके प्रारंभिक मानों का उपयोग करेगा और अपडेट कभी नहीं देखेगा। इसे स्टेल कैप्चर (stale capture) कहा जाता है और यह अक्सर मुश्किल से खोजे जाने वाले बगों का स्रोत होता है।

डिपेंडेंसी ऐरेव्यवहारक्लास समतुल्य
बिना तर्कहर रेंडर के बादcomponentDidUpdate
[]माउंट पर एक बारcomponentDidMount
[a, b]जब a या b बदलता हैComponentWillReceiveProps एनालॉग
क्लीनअप रिटर्नअनमाउंटिंग प्रबंधित करें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 का उपयोग करता है, लेकिन डिपेंडेंसी ऐरे खाली है। परिणामस्वरूप, इफेक्ट प्रारंभिक userId मान के साथ एक बार चलता है और इसके परिवर्तनों पर कभी प्रतिक्रिया नहीं करता। डेवलपर देखता है कि कंपोनेंट एक नया userId प्राप्त कर रहा है, लेकिन डेटा अपडेट नहीं होता। exhaustive-deps नियम के साथ eslint-plugin-react-hooks ऐसे बग स्वचालित रूप से खोजता है।

  • अनंत लूप — इफेक्ट के अंदर स्टेट अपडेट करना, जिससे पुनर्रेंडर होता है जो इफेक्ट को फिर से चलाता है। समाधान: डिपेंडेंसी ऐरे जाँचें या सेटर के फंक्शनल रूप का उपयोग करें।
  • रेस कंडीशन — यदि 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 में ऐसा तर्क डालने से बचें जो पिछले स्टेट के आधार पर स्टेट अपडेट करता है। 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 एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें