- समझें कि useState कार्यात्मक अपडेट और ऑब्जेक्ट हैंडलिंग सहित स्थानीय घटक स्थिति को कैसे संरक्षित और अपडेट करता है।
- स्पष्ट सेटअप/क्लीनअप लॉजिक और सटीक डिपेंडेंसी एरे के साथ साइड इफेक्ट्स के लिए useEffect का उपयोग करें ताकि लीक और लूप से बचा जा सके।
- फंक्शन कंपोनेंट्स में डेटा फ़ेचिंग, सब्सक्रिप्शन और DOM अपडेट जैसे वास्तविक दुनिया के कार्यों के लिए useState और useEffect को संयोजित करें।
- रिएक्ट कंपोनेंट्स को पूर्वानुमानित और रखरखाव योग्य बनाए रखने के लिए हुक्स के नियमों का पालन करें और प्रभावों को "रेंडर के बाद" की प्रक्रियाओं के रूप में मानें।

React हुक्स ने कंपोनेंट लिखने के तरीके को पूरी तरह से बदल दिया है।, और महारत हासिल करना useState और useEffect यह मूल रूप से आधुनिक रिएक्ट कोड लिखने का प्रवेश द्वार है। यदि आप पहले से ही इनका उपयोग करते हैं लेकिन फिर भी अनंत लूप, पुरानी स्थिति या जटिल निर्भरता सरणियों जैसी समस्याओं में फंस जाते हैं, तो यह गाइड आपको व्यावहारिक तरीके से सभी कमियों को दूर करने में मदद करेगी।
इस लेख में हम इसके सही उपयोग के बारे में विस्तार से जानेंगे। useState और useEffect एक साथहुक्स को पहली बार क्यों पेश किया गया, आधिकारिक नियम और सावधानियां, निर्भरताएं वास्तव में कैसे काम करती हैं, आपके घटकों को खराब करने वाली सामान्य कमियां, और वास्तविक परियोजनाओं में साइड इफेक्ट्स, क्लीनअप और स्टेट मैनेजमेंट के लिए आजमाए हुए पैटर्न।
हुक्स क्यों, और विशेष रूप से useState और useEffect क्यों?
React 16.8 में हुक्स को जोड़ा गया था ताकि फंक्शन कंपोनेंट्स बिना क्लास के स्टेट और लाइफसाइकिल सुविधाओं का उपयोग कर सकें।इससे पहले, आपको स्थानीय स्थिति बनाए रखने, बाहरी डेटा की सदस्यता लेने या माउंटिंग और अनमाउंटिंग जैसी जीवनचक्र घटनाओं पर प्रतिक्रिया करने के लिए क्लास कंपोनेंट लिखने पड़ते थे।
क्लासेस के साथ सबसे बड़ी समस्या यह थी कि संबंधित लॉजिक अक्सर कई लाइफसाइकिल मेथड्स में विभाजित हो जाता था। जैसे componentDidMount, componentDidUpdate और componentWillUnmount. इसके परिणामस्वरूप आपको एक ही विशेषता के कुछ अंश अलग-अलग तरीकों में बिखरे हुए मिलेंगे, जो इस पर आधारित होंगे। कब वे इसके बजाय भागते हैं क्या वे ऐसा करते हैं, जिससे कोड को पढ़ना, परीक्षण करना और पुन: उपयोग करना कठिन हो जाता है।
हुक इस मॉडल को पलट देते हैं: साथ useState आप स्टेट को सीधे फंक्शन कंपोनेंट से जोड़ते हैं, और इसके साथ useEffect आप साइड इफेक्ट्स को सीधे उस लॉजिक से जोड़ते हैं जिसे उनकी आवश्यकता होती है। इस तरह आप एक ही समस्या से संबंधित सभी चीजों को एक ही स्थान पर समूहित कर सकते हैं और बाद में आसानी से पुन: उपयोग योग्य हुक्स निकाल सकते हैं।
सभी हुकों में से, useState और useEffect मूल तत्व हैंआप इन दो की मदद से ही अधिकांश रोजमर्रा की सुविधाओं का निर्माण कर सकते हैं: फॉर्म और टॉगल जैसी यूआई स्थिति, नेटवर्क अनुरोध, सदस्यता, टाइमर, डीओएम अपडेट और बहुत कुछ। अन्य हुक (useRef, useReducer, useContext, useMemo…) बहुत अच्छे हैं, लेकिन वे एक ही विचारों पर आधारित हैं।
React हुक्स के वे नियम जिन्हें आपको कभी नहीं तोड़ना चाहिए
रिएक्ट हुक्स कुछ सख्त नियमों के साथ आते हैं जो उन्हें रेंडरिंग के दौरान विश्वसनीय रूप से काम करने में सक्षम बनाते हैं।यदि आप इनका उल्लंघन करते हैं, तो आपको या तो रनटाइम त्रुटियां दिखाई देंगी या बहुत सूक्ष्म, डीबग करने में मुश्किल बग दिखाई देंगे।
पहला नियम: हुक्स को केवल रिएक्ट फंक्शन कंपोनेंट्स या कस्टम हुक्स के अंदर ही कॉल करें।आप इसका उपयोग नहीं कर सकते। useState or useEffect क्लास कंपोनेंट्स, रेगुलर यूटिलिटी फंक्शन्स, या किसी भी कंपोनेंट के बाहर। इस तरह का पैटर्न अमान्य है:
import React, { Component, useState } from 'react';
class App extends Component {
// ❌ This will throw - hooks don’t work in classes
const = useState(0);
render() {
return <h1>Hello, I am a Class Component!</h1>;
}
}
हुक्स का उपयोग करने के लिए सही तरीका फंक्शन कंपोनेंट पर जाना है।:
import React, { useState } from 'react';
function App() {
const = useState('');
return (
<div>
Your JSX code goes in here...
</div>
);
}
export default App;
दूसरा नियम: हुक्स को केवल अपने कंपोनेंट के शीर्ष स्तर पर ही कॉल करें।इसका मतलब है कि लूप, कंडीशन या नेस्टेड फंक्शन के अंदर हुक का इस्तेमाल नहीं किया जा सकता। रिएक्ट हर रेंडर पर हुक को एक ही क्रम में कॉल करने पर निर्भर करता है ताकि हर एक को "मैच" किया जा सके। useState और useEffect इसमें संग्रहीत डेटा के साथ कॉल करना अमान्य है:
function BadComponent({ enabled }) {
if (enabled) {
// ❌ Wrong: hook inside a conditional
const = useState(0);
}
// ...
}
इसके बजाय, हुक्स को बिना शर्त सबसे ऊपर घोषित करें और इफेक्ट या JSX के अंदर कंडीशनल स्टेटमेंट का उपयोग करें।हुक को हमेशा कॉल किया जाना चाहिए, लेकिन इसके द्वारा चलाया जाने वाला लॉजिक सशर्त हो सकता है:
function ConditionalEffectComponent() {
const = useState(false);
useEffect(() => {
if (isMounted) {
console.log('Component mounted');
}
}, );
return (
<div>
<button onClick={() => setIsMounted(!isMounted)}>
{isMounted ? 'Unmount' : 'Mount'}
</button>
</div>
);
}
तीसरा अंतर्निहित नियम यह है कि हुक्स को रिएक्ट (या किसी हुक लाइब्रेरी) से इम्पोर्ट किया जाना चाहिए, न कि उन्हें अलग से लागू किया जाना चाहिए।यह बात स्पष्ट है, लेकिन फिर भी कहना उचित है: असली जादू रिएक्ट के आंतरिक हुक डिस्पैचर में है जो रेंडरिंग के दौरान हुक कॉल को ट्रैक करता है।
useState का उपयोग करके स्थानीय स्थिति को सही ढंग से प्रबंधित करना
useState यह आपको किसी फ़ंक्शन कंपोनेंट से स्टेट अटैच करने और वर्तमान मान और अपडेटर फ़ंक्शन दोनों प्राप्त करने की सुविधा देता है।अवधारणात्मक रूप से यह इसका कार्यात्मक प्रतिरूप है। this.state और this.setState कक्षा घटकों में।
एक न्यूनतम प्रति उदाहरण के साथ useState इस तरह दिखता है:
import React, { useState } from 'react';
function Counter() {
const = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Counter;
जब तुमने फोन किया useState(initialValue)React उस स्थिति को संग्रहीत करता है और एक जोड़ी लौटाता है।: वर्तमान स्थिति मान और एक सेटर। सामान्य स्थानीय चरों के विपरीत, स्थिति रेंडरिंग के दौरान बनी रहती है, इसलिए count कंपोनेंट फ़ंक्शन के चलने पर मान हर बार 0 पर रीसेट नहीं होता है।
आप स्टेट के लिए किसी भी सीरियलाइज़ेबल वैल्यू का उपयोग कर सकते हैं: संख्याएँ, स्ट्रिंग, बूलियन, एरे, ऑब्जेक्ट और यहाँ तक कि फ़ंक्शन भी।आप कॉल भी कर सकते हैं useState एक ही कंपोनेंट में कई बार इसका उपयोग संबंधित मानों को अलग रखने के लिए किया जाता है, बजाय इसके कि सब कुछ एक ही ऑब्जेक्ट में डाल दिया जाए।
जब नया स्टेट मान पिछले मान पर निर्भर करता है, तो हमेशा फंक्शनल अपडेट फॉर्म का उपयोग करें।इससे एक के बाद एक कई स्टेट अपडेट होने पर बग्स से बचा जा सकता है:
setCount(prev => prev + 1);
एक और सूक्ष्म लेकिन महत्वपूर्ण बात यह है कि सेटर को कॉल करने से संपूर्ण स्टेट वैल्यू बदल जाती है, यह ऑब्जेक्ट्स को मर्ज नहीं करती है। this.setState कक्षाओं मेंयदि आपकी स्थिति एक ऑब्जेक्ट या ऐरे है, तो आपको पिछले मान को स्वयं फैलाना होगा:
const = useState({ name: 'Alex', age: 30 });
// ✅ Correct: copy and update
setUser(prev => ({ ...prev, age: prev.age + 1 }));
महंगे प्रारंभिक मानों के लिए, आप एक फ़ंक्शन पास करके स्टेट को लेज़ी-इनिशियलाइज़ कर सकते हैं। useStateReact इसे केवल पहले रेंडर पर ही कॉल करेगा:
const = useState(() => calculateInitialValue());
उपयोग के दौरान होने वाले दुष्प्रभावों से निपटना
useEffect यह फंक्शन कंपोनेंट्स में साइड इफेक्ट्स चलाने के लिए रिएक्ट का एपीआई है।"साइड इफेक्ट" वह सब कुछ है जो बाहरी दुनिया को प्रभावित करता है: डेटा फ़ेचिंग, लॉगिंग, डायरेक्ट DOM परिवर्तन, सब्सक्रिप्शन, टाइमर, ब्राउज़र API आदि।
वैचारिक रूप से, useEffect एक संयोजन को प्रतिस्थापित करता है componentDidMount, componentDidUpdate और componentWillUnmount क्लास घटकों सेकिसी एक प्रभाव को तीन लाइफसाइकिल विधियों में विभाजित करने के बजाय, आप इसे एक बार घोषित करते हैं और रिएक्ट को यह संभालने देते हैं कि यह कब चलता है और कब सफाई करता है।
मूल हस्ताक्षर है useEffect(setup, dependencies?)। setup यह फ़ंक्शन आपका प्रभाव निकाय है; यह वैकल्पिक रूप से एक क्लीनअप फ़ंक्शन लौटा सकता है। dependencies एरे रिएक्ट को बताता है कि प्रभाव को कब दोबारा चलाने की आवश्यकता है।
useEffect(() => {
// side effect logic here
return () => {
// optional cleanup logic here
};
}, );
डिफ़ॉल्ट रूप से, दूसरे तर्क के बिना, प्रभाव प्रत्येक रेंडर के बाद चलेगा। (पहला माउंट और उसके बाद का हर अपडेट)। यह अक्सर नेटवर्क अनुरोधों या जटिल लॉजिक के लिए बहुत अधिक होता है।
एक बहुत ही सामान्य पैटर्न यह है कि जब भी किसी स्टेट में बदलाव होता है, तो किसी बाहरी चीज़ को अपडेट किया जाता है।उदाहरण के लिए, क्लिक की संख्या के आधार पर पेज का शीर्षक अपडेट करना:
import React, { useState, useEffect } from 'react';
function Counter() {
const = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, ); // effect re-runs only when `count` changes
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
</div>
);
}
प्रदर्शन और शुद्धता के लिए निर्भरता सरणी अत्यंत महत्वपूर्ण है।यह नियंत्रित करता है कि रिएक्ट को प्रभाव को कब पुनः चलाना चाहिए: यदि किसी भी निर्भरता में परिवर्तन हुआ है तो। Object.is तुलना करने पर, प्रभाव साफ हो जाता है और फिर से चलता है; यदि कोई परिवर्तन नहीं हुआ है, तो इसे छोड़ दिया जाता है।
डिपेंडेंसी ऐरे को एक पेशेवर की तरह समझना
डिपेंडेंसी ऐरे वह जगह है जहां सबसे सूक्ष्म useEffect कीड़े आते हैंReact, ऐरे के प्रत्येक तत्व की तुलना उसके पिछले मान से करता है। Object.isयदि सभी मान बराबर हैं, तो प्रभाव को छोड़ दिया जाता है; यदि कम से कम एक मान भिन्न है, तो प्रभाव को पुनः निष्पादित किया जाता है।
तीन मुख्य निर्भरता कॉन्फ़िगरेशन हैं जिनका आप हर समय उपयोग करेंगे।:
- कोई दूसरा तर्क नहींयह प्रभाव प्रत्येक रेंडर के बाद चलता है।
- खाली सरणी
[]: यह प्रभाव केवल माउंट होने पर एक बार चलता है और अनमाउंट होने पर सफाई करता है। - मानों वाला ऐरे
यह प्रभाव माउंट होने के बाद और किसी भी निर्भरता में परिवर्तन होने पर लागू होता है।
जब निर्भरताएँ प्राथमिक मान (संख्याएँ, स्ट्रिंग, बूलियन) होती हैं, तो यह सीधा-सादा होता है।समस्या तब शुरू होती है जब आप निर्भरताओं के अंदर ऑब्जेक्ट, एरे या फ़ंक्शन डालते हैं, क्योंकि समानता संदर्भ-आधारित होती है। अलग-अलग संदर्भों वाले दो समान ऑब्जेक्ट को "अलग" माना जाता है, जिससे प्रत्येक रेंडर पर पुनः रन करना पड़ता है।
एक ऐसे प्रभाव पर विचार करें जो इस पर निर्भर करता है team प्रॉप्स से ऑब्जेक्ट:
function Team({ team }) {
useEffect(() => {
console.log(team.id, team.active);
}, ); // ⚠️ might re-run every render if `team` reference changes
}
भले ही टीम की वास्तविक सामग्री में कोई बदलाव न हो, प्रत्येक रेंडर पर एक नया ऑब्जेक्ट संदर्भ प्रभाव को फिर से चलाने के लिए बाध्य करेगा।इससे बचने के लिए, या तो उन प्राथमिक क्षेत्रों पर निर्भर रहें जिनका आप वास्तव में उपयोग करते हैं, या प्रभाव के भीतर ही वस्तु का पुनर्निर्माण करें।
एक सुरक्षित संस्करण केवल उसी चीज़ को ट्रैक करता है जिसकी वास्तव में प्रभाव को आवश्यकता होती है।:
function Team({ team }) {
const { id, active } = team;
useEffect(() => {
console.log(id, active);
}, );
}
यदि आपको वास्तव में प्रभाव के भीतर पूरी वस्तु की आवश्यकता है, तो आप इसे निर्भरता के रूप में उपयोग करने के बजाय वहीं पुनः बना सकते हैं।इस तरह निर्भरता सूची अभी भी मूल तत्वों पर आधारित हो सकती है:
function Team({ team }) {
const { id, active, name } = team;
useEffect(() => {
const localTeam = { id, active, name };
// use `localTeam` here
}, );
}
अंतिम उपाय के रूप में आप मेमोइज़ेशन का उपयोग कर सकते हैं। useMemo or useCallback महंगी वस्तुओं या कार्यों के लिएलेकिन याद रखें कि मेमोइज़ेशन की भी अपनी कुछ लागत होती है। इसे हर जगह "ज़रूरत पड़ने पर" इस्तेमाल न करें; इसे तभी जोड़ें जब कोई विशिष्ट निर्भरता वास्तव में प्रदर्शन संबंधी समस्याएं पैदा कर रही हो।
प्रभावों को सही ढंग से साफ़ करना
कुछ दुष्प्रभावों के कारण ऐसे संसाधन आवंटित हो जाते हैं जिन्हें मुक्त करना आवश्यक होता है।सब्सक्रिप्शन, सॉकेट, इंटरवल, टाइमआउट, इवेंट लिसनर आदि। इन्हें साफ करना भूल जाने से आसानी से मेमोरी लीक या दोहराव वाला काम हो सकता है।
In useEffectसफाई का कार्य प्रभाव से एक फ़ंक्शन लौटाकर किया जाता है।React इस फ़ंक्शन को नए डिपेंडेंसी के साथ इफ़ेक्ट को दोबारा चलाने से पहले और कंपोनेंट के अनमाउंट होने पर एक आखिरी बार कॉल करेगा।
import { useEffect } from 'react';
function LogMessage({ message }) {
useEffect(() => {
const log = setInterval(() => {
console.log(message);
}, 1000);
return () => {
clearInterval(log);
};
}, );
return <div>logging to console "{message}"</div>;
}
इस उदाहरण में, हर बार message परिवर्तनों के लिए, React पहले पुराने अंतराल को साफ़ करता है, फिर अद्यतन संदेश के साथ एक नया अंतराल सेट करता है।जब कंपोनेंट यूआई से गायब हो जाता है, तो अंतिम क्लीनअप उस अंतराल को पूरी तरह से साफ़ कर देता है।
यह “सेटअप + क्लीनअप” युग्म मानसिक मॉडल का केंद्र है। useEffectप्रत्येक प्रभाव को एक स्व-निहित प्रक्रिया के रूप में समझने का प्रयास करें जो सेटअप फ़ंक्शन में शुरू होती है और क्लीनअप फ़ंक्शन में पूरी तरह से समाप्त हो जाती है। विकास के दौरान (विशेष रूप से स्ट्रिक्ट मोड में) रिएक्ट कई सेटअप/क्लीनअप चक्र चला सकता है ताकि यह सुनिश्चित किया जा सके कि आपका क्लीनअप वास्तव में सब कुछ पूर्ववत कर देता है।
इसका एक उत्कृष्ट उदाहरण चैट एपीआई या ब्राउज़र इवेंट जैसे बाहरी स्रोत की सदस्यता लेना है (देखें React में onKeyDown को हैंडल करना):
useEffect(() => {
function handleClick(event) {
console.log('Clicked', event.clientX, event.clientY);
}
document.addEventListener('click', handleClick);
return () => {
document.removeEventListener('click', handleClick);
};
}, []); // runs once on mount, cleans up on unmount
डेटा प्राप्त करने के लिए useState और useEffect का एक साथ उपयोग करना
वास्तविक दुनिया में सबसे आम संयोजनों में से एक है useState और useEffect API से डेटा प्राप्त करने के लिएआप डेटा (और शायद लोडिंग/त्रुटि फ़्लैग) को स्टेट में रखते हैं, और कंपोनेंट माउंट होने पर या किसी पैरामीटर में बदलाव होने पर चलने वाले इफ़ेक्ट में अनुरोध निष्पादित करते हैं।
माउंट होने पर डेटा प्राप्त करने का एक बुनियादी पैटर्न कुछ इस प्रकार दिखता है।:
import { useEffect, useState } from 'react';
function FetchItems() {
const = useState([]);
useEffect(() => {
let ignore = false;
async function fetchItems() {
try {
const response = await fetch('/items');
const fetchedItems = await response.json();
if (!ignore) {
setItems(fetchedItems);
}
} catch (error) {
console.error('Error fetching items:', error);
}
}
fetchItems();
return () => {
// avoid updating state if the component unmounted
ignore = true;
};
}, []);
return (
<div>
{items.map(item => (
<div key={item.id ?? item}>{item.name ?? item}</div>
))}
</div>
);
}
यहां, खाली डिपेंडेंसी ऐरे यह सुनिश्चित करता है कि अनुरोध केवल एक बार ही चले।। आंतरिक ignore अनुरोध के देर से हल होने की स्थिति में, अनमाउंटेड कंपोनेंट पर स्टेट सेट करने से बचने का एक सरल तरीका फ्लैग है।
डेटा आने के दौरान लोडिंग फ्लैग जोड़ना और स्पिनर या प्लेसहोल्डर दिखाना भी बहुत आम बात है।:
const Statistics = () => {
const = useState([]);
const = useState(true);
useEffect(() => {
const getStats = async () => {
try {
const statsData = await getData();
setStats(statsData);
} finally {
setLoading(false);
}
};
getStats();
}, []);
if (loading) {
return <div>Loading statistics...</div>;
}
return (
<ul>
{stats.map(stat => (
<li key={stat.id}>{stat.label}: {stat.value}</li>
))}
</ul>
);
};
यदि आपकी क्वेरी किसी पैरामीटर (जैसे श्रेणी, फ़िल्टर या रूट पैरामीटर) पर निर्भर करती है, तो उस पैरामीटर को डिपेंडेंसी ऐरे में जोड़ें। इसलिए परिवर्तन होने पर प्रभाव पुनः चलता है:
useEffect(() => {
async function fetchItems() {
const response = await fetch(`/items?category=${category}`);
const data = await response.json();
setItems(data);
}
fetchItems();
}, );
“प्रत्येक रेंडर पर प्रभाव” बनाम “जीवनचक्र” के बारे में सोचना
यदि आप क्लास कंपोनेंट्स से परिचित हैं, तो मानसिक रूप से मैपिंग करना आकर्षक लग सकता है। useEffect माउंट/अपडेट/अनमाउंट करने के तरीकेलेकिन इससे आमतौर पर और अधिक भ्रम पैदा होता है। एक सरल मानसिक मॉडल यह है: "इफेक्ट्स रेंडर होने के बाद चलते हैं, और अगले रन से पहले सफाई कर सकते हैं"।
कक्षाओं में, आपको अक्सर तर्क को दोहराना पड़ता था। componentDidMount और componentDidUpdate क्योंकि आप माउंट और अपडेट दोनों पर एक ही प्रभाव चाहते थे। हुक्स के साथ, यह दोहराव खत्म हो जाता है: एक ही प्रभाव दोनों मामलों को कवर करता है, और रिएक्ट रन के बीच सफाई का ध्यान रखता है।
यह डिज़ाइन अपडेट को सही ढंग से हैंडल न करने से संबंधित कई तरह की समस्याओं को भी खत्म कर देता है।उदाहरण के लिए, किसी क्लास कंपोनेंट में जो किसी मित्र की ऑनलाइन स्थिति को सब्सक्राइब करता है, जब आप दोबारा सब्सक्राइब करना भूल जाते हैं तो यह आसान होता है। props.friend परिवर्तन, जिससे सदस्यताएँ पुरानी हो जाती हैं या अनमाउंट करने पर क्रैश हो जाता है। useEffect जो सूची बनाता है friend.id एक डिपेंडेंसी के रूप में, रिएक्ट स्वचालित रूप से पुराने फ्रेंड के लिए क्लीनअप और नए फ्रेंड के लिए सेटअप चलाएगा।
ध्यान रखें कि डेवलपमेंट स्ट्रिक्ट मोड में, रिएक्ट जानबूझकर माउंट होने पर आपके सेटअप और क्लीनअप चक्र को दो बार चलाता है।यह उत्पादन में नहीं होता है, लेकिन यह एक उपयोगी स्ट्रेस टेस्ट है यह पुष्टि करने के लिए कि आपका क्लीनअप वास्तव में सब कुछ पूर्ववत कर देता है और आपका प्रभाव सुरक्षित रूप से कई बार चल सकता है।
उपयोग प्रभाव व्यवहार को अनुकूलित करना और उसमें आने वाली समस्याओं का निवारण करना
जब कोई प्रभाव आपकी अपेक्षा से अधिक बार चलता है, तो सबसे पहले निर्भरता सरणी की जाँच करें।या तो प्रत्येक रेंडर पर कोई निर्भरता बदल जाती है (इनलाइन ऑब्जेक्ट/फ़ंक्शंस के साथ आम बात है) या आप सरणी को निर्दिष्ट करना ही भूल गए हैं।
निर्भरता मूल्यों को लॉग करना डिबग करने का एक त्वरित तरीका है।:
useEffect(() => {
console.log('Effect deps:', dep1, dep2);
}, );
यदि आपको हर बार अलग-अलग लॉग दिखाई देते हैं, तो जांचें कि वास्तव में कौन सी निर्भरता बदल रही है।अक्सर आपको प्रत्येक रेंडर पर एक इनलाइन ऑब्जेक्ट या एरो फ़ंक्शन को फिर से बनाते हुए मिलेगा। ऑब्जेक्ट निर्माण को इफ़ेक्ट के अंदर ले जाना, या फ़ंक्शन को कंपोनेंट के बाहर ले जाना, या उन्हें मेमोराइज़ करना... useCallback आवश्यकता पड़ने पर निर्भरताओं को स्थिर कर सकता है।
अनंत लूप तब उत्पन्न होते हैं जब कोई प्रभाव किसी मान पर निर्भर करता है और उसी मान को बिना शर्त अपडेट करता है।। उदाहरण के लिए:
useEffect(() => {
setCount(count + 1); // ⚠️ will cause a loop if `count` is a dependency
}, );
हर बार count परिवर्तन, प्रभाव जारी रहता है, अपडेट count फिर, यह एक और रेंडर को ट्रिगर करता है, और इसी तरह आगे भी।इस पैटर्न को तोड़ने के लिए, विचार करें कि क्या स्टेट अपडेट वास्तव में किसी प्रभाव में होना चाहिए, क्या इसे उपयोगकर्ता की बातचीत से ट्रिगर किया जाना चाहिए, या क्या आप किसी अलग मान पर निर्भर कर सकते हैं।
कभी-कभी आप किसी इफ़ेक्ट के अंदर किसी स्टेट या प्रॉप्स का नवीनतम मान पढ़ना चाहते हैं, लेकिन यह नहीं चाहते कि वह मान री-रन को ट्रिगर करे।उन उन्नत परिदृश्यों में, "इफ़ेक्ट इवेंट्स" जैसे नए एपीआई (के माध्यम से) useEffectEvent (React डॉक्स में) या रेफ़्स मदद कर सकते हैं, लेकिन अधिकांश व्यावहारिक मामलों में, निर्भरताओं के प्रति वफादार रहना अधिक सुरक्षित और सरल है।
सब कुछ एक साथ मिलाकर, उपयोग करना useState और useEffect सही मायने में इसका सार कुछ मूलभूत आदतों में समाहित है।स्टेट को छोटा और केंद्रित रखें, पुराने स्टेट से नया स्टेट बनाते समय फंक्शनल अपडेट को प्राथमिकता दें, सेटअप/क्लीनअप पेयर के आधार पर इफेक्ट्स को स्ट्रक्चर करें, डिपेंडेंसी एरे के साथ स्पष्ट और सटीक रहें, और हुक्स के नियमों का हमेशा पालन करें ताकि रिएक्ट विश्वसनीय रूप से ट्रैक कर सके कि कौन सा कोड कहाँ है। इन सिद्धांतों का पालन करने से आपके कंपोनेंट्स पूर्वानुमानित रहते हैं, साइड इफेक्ट्स सही ढंग से काम करते हैं, और जैसे-जैसे आपका ऐप बढ़ता है, आपका रिएक्ट कोडबेस विकसित करना बहुत आसान हो जाता है।