🌐 Detecting your location…

प्रतिक्रिया उपयोग प्रभाव अनंत लूप: ऐसा क्यों होता है और वास्तव में इसे कैसे ठीक करें

⏱️2 min read  ·  384 words

A प्रतिक्रिया उपयोग प्रभाव अनंत लूप हुक सीखने वाले डेवलपर्स के लिए सबसे आम बग में से एक है। आपका घटक पुन: प्रस्तुत करता है, प्रभाव को ट्रिगर करता है, जो एक और रेंडर का कारण बनता है, जो प्रभाव को फिर से ट्रिगर करता है – जब तक कि ब्राउज़र क्रैश नहीं हो जाता। यहां बताया गया है कि ऐसा क्यों होता है और प्रत्येक प्रकार को कैसे ठीक किया जाए।

अनंत लूप क्यों होते हैं

रिएक्ट घटक का प्रत्येक पुन: प्रस्तुतीकरण घटक के अंदर परिभाषित वस्तुओं, सरणियों और कार्यों के लिए नए संदर्भ बनाता है। यदि आपकाuseEffect निर्भरता सरणी में इनमें से एक मान होता है, रिएक्ट प्रत्येक रेंडर पर एक “नई” निर्भरता देखता है – भले ही डेटा तार्किक रूप से समान हो – और फिर से प्रभाव चलाता है, जिससे एक और पुन: रेंडर होता है, एक और लूप बनता है।

कारण 1: निर्भरता के बिना राज्य की स्थापना (सबसे सामान्य)

// 🐛 Bug: runs after every render, sets state, causes re-render
useEffect(() => {
 setCount(count + 1); // state update → re-render → effect runs again
}); // no dependency array = runs after EVERY render

// ✅ Fix: empty dependency array = run once on mount only
useEffect(() => {
 setCount(prevCount => prevCount + 1);
}, []); // runs once

कारण 2: निर्भरता सरणी में वस्तु

// 🐛 Bug: new object reference on every render
function UserProfile({ userId }) {
 const options = { method: 'GET', headers: { 'Auth': 'token' } }; // NEW object each render

 useEffect(() => {
 fetchUser(userId, options);
 }, [options]); // options is always "new" → infinite loop
}

// ✅ Fix 1: move object outside component (if it's static)
const OPTIONS = { method: 'GET', headers: { 'Auth': 'token' } }; // defined once

function UserProfile({ userId }) {
 useEffect(() => {
 fetchUser(userId, OPTIONS);
 }, [userId]); // only depends on userId
}

// ✅ Fix 2: useMemo if the object depends on props
function UserProfile({ userId, token }) {
 const options = useMemo(
 () => ({ method: 'GET', headers: { 'Auth': token } }),
 [token] // only recreates when token changes
 );

 useEffect(() => {
 fetchUser(userId, options);
 }, [userId, options]);
}

कारण 3: निर्भरता सरणी में कार्य

// 🐛 Bug: new function reference on every render
function DataFetcher({ id }) {
 const fetchData = async () => { // NEW function each render
 const data = await api.get(id);
 setData(data);
 };

 useEffect(() => {
 fetchData();
 }, [fetchData]); // fetchData is always "new" → infinite loop
}

// ✅ Fix: useCallback to memoize the function
function DataFetcher({ id }) {
 const fetchData = useCallback(async () => {
 const data = await api.get(id);
 setData(data);
 }, [id]); // only recreates when id changes

 useEffect(() => {
 fetchData();
 }, [fetchData]); // stable reference now
}

// ✅ Alternative: define function INSIDE the effect
useEffect(() => {
 const fetchData = async () => {
 const data = await api.get(id);
 setData(data);
 };
 fetchData();
}, [id]); // clean, no useCallback needed

कारण 4: निर्भरता के रूप में राज्य के साथ राज्य अद्यतन

// 🐛 Bug: count is dependency AND being updated inside effect
useEffect(() => {
 const timer = setInterval(() => {
 setCount(count + 1); // depends on count → loop
 }, 1000);
 return () => clearInterval(timer);
}, [count]); // re-runs every time count changes

// ✅ Fix: use functional state update (no dependency on count)
useEffect(() => {
 const timer = setInterval(() => {
 setCount(prev => prev + 1); // no dependency on count needed
 }, 1000);
 return () => clearInterval(timer);
}, []); // runs once, updates count independently

कारण 5: निर्भरता सारणी में सारणी

// 🐛 Bug: new array reference on every render
function List({ items }) {
 const filtered = items.filter(i => i.active); // NEW array each render

 useEffect(() => {
 processItems(filtered);
 }, [filtered]); // always "new" → infinite loop
}

// ✅ Fix: useMemo to stabilize the array
function List({ items }) {
 const filtered = useMemo(
 () => items.filter(i => i.active),
 [items]
 );

 useEffect(() => {
 processItems(filtered);
 }, [filtered]);
}

किसी भी अनंत लूप को कैसे डीबग करें

  1. उपयोग से पहले कंसोल.लॉग जोड़ें: देखें कि घटक कितनी बार पुन: प्रस्तुत होता है।
  2. प्रभाव के अंदर राज्य अद्यतन पर टिप्पणी करें: यदि लूप बंद हो जाता है, तो राज्य अद्यतन इसका कारण है।
  3. प्रत्येक निर्भरता को लॉग करें: console.log('dep1:', dep1, 'dep2:', dep2) प्रभाव के अंदर यह देखने के लिए कि कौन सा परिवर्तन हुआ।
  4. ESLint रिएक्ट-हुक प्लगइन का उपयोग करें: eslint-plugin-react-hooks झंडे स्वचालित रूप से गायब निर्भरताएँ।

त्वरित संदर्भ: प्रत्येक हुक का उपयोग कब करें

हुक के लिए उपयोग करें उपयोग प्रभाव
दुष्प्रभाव: डेटा प्राप्त करना, सदस्यताएँ, DOM हेरफेर यूज़मेमो
महँगे परिकलित मान – प्रत्येक रेंडर पर पुनर्गणना को रोकता है कॉलबैक का उपयोग करें
फ़ंक्शंस को याद किए गए बच्चों के लिए निर्भरता या प्रॉप्स के रूप में पारित किया गया उपयोगRef
वे मान जो परिवर्तित होने पर पुन: प्रस्तुतीकरण को ट्रिगर नहीं करना चाहिए अक्सर पूछे जाने वाले प्रश्न

प्रश्न: मुझे खाली निर्भरता सरणी का उपयोग कब करना चाहिए?

उ: जब प्रभाव माउंट पर केवल एक बार चलना चाहिए (उदाहरण के लिए, प्रारंभिक डेटा प्राप्त करें, सदस्यता सेट करें)। सावधान रहें – यह आरंभिक स्थिति मानों पर एक अवरोध पैदा करता है।
प्रश्न: क्या मुझे हमेशा निर्भरता सरणी में सब कुछ शामिल करना चाहिए?

उत्तर: हां, रिएक्ट के नियमों के अनुसार। यदि किसी चीज़ को शामिल करने से लूप बनता है, तो वास्तविक समाधान उस मान को यूज़मेमो/यूज़कॉलबैक के साथ स्थिर करना है, न कि उसे डिप्स से हटाना।
प्रश्न: यूज़मेमो और यूज़कॉलबैक के बीच क्या अंतर है?

किसी मान को याद रखता है (उदाहरण के लिए, एक फ़िल्टर किया गया सरणी)।
A: useMemo किसी फ़ंक्शन को याद रखता है. दोनों प्रत्येक रेंडर पर अनावश्यक पुन: निर्माण को रोकते हैं।useCallbackप्रश्न: रिएक्ट विकास में दो बार यूज़इफेक्ट क्यों चलाता है?

उत्तर: रिएक्ट 18 स्ट्रिक्ट मोड उन साइड इफेक्ट्स को खोजने में मदद करने के लिए जानबूझकर विकास में दो बार प्रभाव चलाता है जो ठीक से साफ नहीं होते हैं। उत्पादन में ऐसा नहीं होता.
प्रश्न: क्या मैं ईएसलिंट के एग्जॉस्टिव-डिप्स नियम को अक्षम कर सकता हूं?

उत्तर: आप कर सकते हैं, लेकिन आपको नहीं करना चाहिए। नियम मौजूद है क्योंकि गायब निर्भरताएँ सूक्ष्म बग का कारण बनती हैं। चेतावनी को अक्षम करने के बजाय अंतर्निहित समस्या को ठीक करें।
निष्कर्ष

प्रतिक्रिया उपयोग प्रभाव अनंत लूप हमेशा एक मूल कारण पर आते हैं:

एक निर्भरता जो प्रत्येक रेंडर पर एक नया संदर्भ बनाती है, जिससे प्रभाव फिर से चलता है, जो एक और रेंडर को ट्रिगर करता है. समाधान हमेशा उस संदर्भ कोका उपयोग करके स्थिर करना होता है , या मान को घटक के बाहर ले जाकर। एक बार जब आप “समान संदर्भ = दोबारा चलाने की आवश्यकता नहीं” मानसिक मॉडल को आत्मसात कर लेते हैं, तो इन बग को रोकना आसान हो जाता है और डीबग करना तेज़ हो जाता है।useMemo, useCallback, useRefका उपयोग करके स्थिर करना होता है , या मान को घटक के बाहर ले जाकर। एक बार जब आप “समान संदर्भ = दोबारा चलाने की आवश्यकता नहीं” मानसिक मॉडल को आत्मसात कर लेते हैं, तो इन बग को रोकना आसान हो जाता है और डीबग करना तेज़ हो जाता है।

MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা