useEffect एक React हुक है जो आपको फंक्शनल कंपोनेंट्स में साइड इफेक्ट्स निष्पादित करने की अनुमति देता है, जो क्लास कंपोनेंट्स के जीवनचक्र विधियों को प्रतिस्थापित करता है: componentDidMount, componentDidUpdate और componentWillUnmount। React Documentation (2025) के अनुसार, useEffect तब निष्पादित होता है जब React ने DOM में परिवर्तनों को कमिट कर दिया है, जो वास्तविक DOM ट्री तक पहुँच सुनिश्चित करता है। हुक एक इफेक्ट फ़ंक्शन और एक वैकल्पिक डिपेंडेंसी ऐरे स्वीकार करता है जो निष्पादन आवृत्ति को नियंत्रित करता है।
मुख्य बिंदु
useEffect एक हुक है जो React 16.8 में फंक्शनल कंपोनेंट्स में साइड इफेक्ट्स करने के लिए जोड़ा गया था। साइड इफेक्ट्स वे ऑपरेशन हैं जो UI रेंडरिंग से सीधे संबंधित नहीं हैं: APIs के लिए 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 को exhaustive-deps नियम के साथ प्रदान करता है, जो स्वचालित रूप से डिपेंडेंसी ऐरे की पूर्णता की जाँच करता है। Meta Engineering Blog (2024) के अनुसार, इस प्लगइन को सक्षम करने से हुक्स से संबंधित बग 72% कम हो जाते हैं। कस्टम तर्क वाले दुर्लभ मामलों को छोड़कर, सभी exhaustive-deps चेतावनियों को टिप्पणी से दबाने के बजाय ठीक करने की अनुशंसा की जाती है।
यदि आप डिपेंडेंसी ऐरे बिल्कुल नहीं देते हैं, तो 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 प्राप्त कर रहा है, लेकिन डेटा अपडेट नहीं होता। 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 में ऐसा तर्क डालने से बचें जो पिछले स्टेट के आधार पर स्टेट अपडेट करता है। 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 एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें