React Hooks ओल फ़ंक्शन्स हैं जो आपको बिना क्लास लिखे फ़ंक्शनल कंपोनेंट्स में स्टेट, इफ़ेक्ट्स, कंटेक्स्ट और React की अन्य सुविधाओं का उपयोग करने की अनुमति देते हैं। React 16.8 में पेश किए गए, हुक ने HOC और render props जैसे जटिल पैटर्न्स को बदलकर विकास दृष्टिकोण को मूलभूत रूप से बदल दिया। React, 2024 के अनुसार, सभी कंपोनेंट प्रबंधन परिदृश्यों को कवर करने वाले 15 बिल्ट-इन हुक हैं।
मुख्य बातें
React Hooks React में निर्मित फ़ंक्शन्स का एक सेट है जो आपको बिना क्लास बनाए फ़्रेमवर्क के आंतरिक तंत्रों से “जुड़ने” की अनुमति देते हैं। React 16.8 से पहले, फ़ंक्शनल कंपोनेंट्स केवल props स्वीकार कर सकते थे और JSX लौटा सकते थे — किसी भी जटिल तर्क के लिए एक क्लास कंपोनेंट की आवश्यकता थी।
क्लास कंपोनेंट्स की समस्या संबंधित तर्क का विभाजन है। एक इकाई से संबंधित कोड (जैसे, एक WebSocket सब्स्क्रिप्शन) को componentDidMount, componentDidUpdate और componentWillUnmount के बीच जबरन विभाजित किया जाता था। हुक इसे हल करते हैं: सभी तर्क एक useEffect में समूहीकृत है।
दूसरी समस्या तर्क पुनःउपयोग है। क्लास कंपोनेंट्स के बीच स्थिति तर्क का पुनःउपयोग करने के लिए, आपको HOC (उच्च-स्तरीय कंपोनेंट) या render props लागू करनी पड़ती थी — दोनों पैटर्न्स ने कंपोनेंट ट्री में अतिरिक्त नेस्टिंग बनाया। कस्टम हुक बिना नेस्टिंग के इसे हल करते हैं।
useState सबसे मौलिक हुक है। यह एक प्रारंभिक मान लेता है और एक टयूपल लौटाता है: वर्तमान मान और इसे अपडेट करने का एक फ़ंक्शन। क्लासों में this.setState के विपरीत, useState ऑब्जेक्ट्स को मर्ज नहीं करता है — नई स्थिति एक विशिष्ट useState कॉल के लिए पिछली स्थिति को पूर्ण रूप से बदल देती है।
import React, { useState } from 'react';
function Form() {
const [text, setText] = useState('');
const [submitting, setSubmitting] = useState(false);
async function handleSubmit() {
setSubmitting(true);
await fetch('/api/submit', {
method: 'POST',
body: JSON.stringify({ text })
});
setSubmitting(false);
}
return (
<div>
<input
value={text}
onChange={e => setText(e.target.value)}
/>
<button onClick={handleSubmit}
disabled={submitting}>
{submitting ? 'Saving...' : 'Submit'}
</button>
</div>
);
}
useState सेटर एक फ़ंक्शन स्वीकार कर सकता है जो पिछला मान प्राप्त करता है और एक नया मान लौटाता है। फ़ंक्शनल प्रारूप आवश्यक है जब नई स्थिति पिछली स्थिति से गणना की जाती है और बैच की गई setState कॉल्स संभव हैं — प्रत्येक कॉल को वर्तमान पिछला मान प्राप्त होगा।
useEffect फ़ंक्शनल कंपोनेंट्स में साइड इफ़ेक्ट करने के लिए एक हुक है। यह दो आर्गुमेंट लेता है: एक इफ़ेक्ट फ़ंक्शन और एक निर्भरता अरे। React प्रत्येक रेंडर के बाद इफ़ेक्ट चलाता है, लेकिन जब निर्भरताएँ निर्दिष्ट की जाती हैं — केवल जब उनमें से कोई बदलती है।
एक खाली निर्भरता अरे [] का मतलब है कि इफ़ेक्ट पहले रेंडर के बाद एक बार चलता है (componentDidMount के समान). इफ़ेक्ट से एक फ़ंक्शन लौटाना एक सफाई है जो अनमौंट पर चलती है (componentWillUnmount के समान) और इफ़ेक्ट को फिर से चलाने से पहले।
import React, { useState, useEffect } from 'react';
function ChatRoom({ roomId }) {
const [messages, setMessages] = useState([]);
useEffect(() => {
const socket = new WebSocket(`wss://chat/${roomId}`);
socket.onmessage = (event) => {
setMessages(prev => [...prev, JSON.parse(event.data)]);
};
// सफाई - सॉकेट बंद करें
return () => socket.close();
}, [roomId]);
return <ul>
{messages.map((msg, i) =>
<li key={i}>{msg.text}</li>
)}
</ul>;
}
useEffect निर्भरताएँ इफ़ेक्ट और बाहरी दुनिया के बीच एकमात्र संबंध हैं। यदि इफ़ेक्ट props या स्थिति से एक चर का उपयोग करता है, तो इसे निर्भरता अरे में होना चाहिए। इस नियम की अनदेखी करना पुरानी closures के साथ बग्स का स्रोत है।
useContext कंटेक्स्ट मानों को पढ़ने के लिए एक हुक है। यह React.createContext द्वारा बनाया गया एक कंटेक्स्ट ऑब्जेक्ट लेता है और वर्तमान मान लौटाता है। यदि कंटेक्स्ट बदलता है, तो कंपोनेंट नए मान के साथ स्वचालित रूप से पुनःरेंडर होता है।
useContext से पहले, फ़ंक्शनल कंपोनेंट्स में कंटेक्स्ट तक पहुंचने के लिए Context.Consumer में लपेटने की आवश्यकता थी, जिससे नेस्टिंग बनती थी। useContext Consumer को पूर्ण रूप से समाप्त कर देता है — बस फ़ंक्शनल कंपोनेंट में कहीं भी हुक को कॉल करें।
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('हल्का');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button
className={`btn btn-${theme}`}
>
{theme === 'dark' ? 'moon' : '☀️'}
</button>;
}
useContext Redux या वैश्विक स्थिति का प्रतिस्थापन नहीं है। React कम बदलने वाले मानों — थीम, लोकेल, प्रमाणीकरण स्थिति के लिए कंटेक्स्ट का उपयोग करने की सिफ़ारिश करता है। बार-बार अपडेट होने वाले डेटा के लिए, प्रत्येक पुनःरेंडर सभी कंटेक्स्ट उपभोक्ताओं की पुनःगणना करेगा, जो प्रदर्शन को कम कर सकता है।
useReducer जटिल अपडेट तर्क वाली स्थितियों के लिए useState का एक विकल्प है। यह एक रिड्यूसर फ़ंक्शन और प्रारंभिक स्थिति लेता है, वर्तमान स्थिति और एक dispatch फ़ंक्शन लौटाता है। रिड्यूसर वर्तमान स्थिति और कार्रवाई प्राप्त करता है, एक नई स्थिति लौटाता है — बिना साइड इफ़ेक्ट के एक शुद्ध फ़ंक्शन।
useReducer विशेष रूप से उपयोगी है जब एकाधिक कार्रवाइयाँ (set, reset, increment, addItem) एक स्थिति का प्रबंधन करती हैं। विभिन्न सेटर्स के साथ एकाधिक useState कॉल्स के बजाय — स्पष्ट कार्रवाई प्रकारों के साथ एक रिड्यूसर। यह तर्क को पूर्वानुमानी और आसानी से परीक्षणिय बनाता है।
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'setStep':
return { ...state, step: action.step };
case 'reset':
return { count: 0, step: 1 };
default:
throw new Error('Unknown action: ' + action.type);
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, {
count: 0,
step: 1
});
return (
<>
<p>Count: {state.count}</p>
<button
onClick={() => dispatch({ type: 'increment' })}>+</button>
<button
onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</>
);
}
useRef एक म्यूटेबल ऑब्जेक्ट बनाता है जो रेंडर्स के बीच बना रहता है। current को बदलना पुनर्रेंडर को ट्रिगर नहीं करता। मुख्य उपयोग DOM तत्वों तक पहुंचना और म्यूटेबल मानों (टाइमर, पिछले मान, लाइब्रेरी उदाहरण) को संग्रहीत करना है।
useMemo एक फ़ंक्शन के परिणाम को मेमाइज़ करता है। यह मान की पुनःगणना केवल तभी करता है जब कोई निर्भरता बदलती है। महंगी गणनाओं के लिए इसका उपयोग करें — बड़े अरे को फ़िल्टर करना, सॉर्टिंग, डेटा फ़ॉर्मैटिंग। useCallback फ़ंक्शन्स को मेमाइज़ करने के लिए useMemo का एक विशेष मामला है।
import React, { useRef, useMemo, useCallback } from 'react';
function SearchPage({ items, query, onItemSelect }) {
const inputRef = useRef(null);
// मौंट पर स्वतःफोकस
useEffect(() => {
inputRef.current?.focus();
}, []);
// फ़िल्टर किया गया परिणाम मेमाइज़ करें
const filtered = useMemo(() => {
return items.filter(item =>
item.name.toLowerCase()
.includes(query.toLowerCase())
);
}, [items, query]);
// कॉलबैक मेमाइज़ करें
const handleSelect = useCallback((id) => {
onItemSelect(id);
}, [onItemSelect]);
return (
<div>
<input ref={inputRef}
value={query}
onChange={e => setQuery(e.target.value)}
/>
<ul>
{filtered.map(item =>
<li key={item.id}>
<button
onClick={() => handleSelect(item.id)}>
{item.name}
</button>
</li>
)}
</ul>
</div>
);
}
एक महत्वपूर्ण नियम: useRef, useMemo और useCallback ऑप्टिमाइजेशन उपकरण हैं, अनिवार्य निर्माण नहीं। सभी कुछ को useMemo में लपेटें — पहले प्रदर्शन मापें। समय से पहले ऑप्टिमाइजेशन कोड को जटिल बनाता है। React कंपोनेंट्स को जल्दी रेंडर करता है; useMemo केवल तभी आवश्यक है जब गणनाएँ वास्तव में महंगी हों (O(n²) और ऊपर).
React ने हुक के लिए दो सत्वार नियम पेश किए। पहला: हुक को केवल उपरी स्तर पर कॉल करें — शर्तों, लूप्स या नेस्टेड फ़ंक्शन्स के अंदर नहीं। दूसरा: हुक को केवल React फ़ंक्शनल कंपोनेंट्स या कस्टम हुक से ही कॉल करें। ESLint प्लगिन eslint-plugin-react-hooks स्वचालित रूप से दोनों नियमों की जाँच करता है।
सबसे आम गलती हुक कॉल के क्रम का उल्लंघन है। React रेंडर्स के बीच हुक कॉल के क्रम पर निर्भर करता है। यदि एक हुक एक शर्त के अंदर है और एक रेंडर में नहीं चलता, तो बाद के सभी हुक शिफ्ट हो जाते हैं, जिससे बग्स होते हैं।
| गलती | क्या होता है | समाधान |
|---|---|---|
| शर्त में हुक | हुक का क्रम टूट जाता है | शर्त तर्क को हुक के अंदर ले जाएँ |
| Stale closure | इफ़ेक्ट पुराना मान उपयोग करता है | सभी निर्भरताएँ अरे में जोड़ें |
| अनंत लूप | useEffect बिना निर्भरताओं के state बदलता है | निर्भरताएँ निर्दिष्ट करें या useReducer का उपयोग करें |
| render में ref बदलना | फ़ंक्शन बोडी में साइड इफ़ेक्ट | म्यूटेशन्स को useEffect में ले जाएँ |
दूसरी आम गलती useEffect में stale closure है। यदि इफ़ेक्ट निर्भरताओं में निर्दिष्ट नहीं किए गए एक चर का उपयोग करता है, तो इफ़ेक्ट क्लोजर निर्माण के समय उसके मान को “कैप्चर” कर लेता है। समाधान हमेशा सभी उपयोग किए गए चरों को निर्भरता अरे में शामिल करना है। यदि बहुत अधिक निर्भरताएँ हैं, तो इफ़ेक्ट को कई भागों में विभाजित करने पर विचार करें।
अक्सर पूछे जाने वाले प्रश्न
React रेंडर्स के बीच हुक कॉल के क्रम पर निर्भर करता है। यदि एक हुक को एक शर्त के अंदर बुलाया जाता है और एक रेंडर में नहीं चलता, तो बाद के सभी हुक शिफ्ट हो जाते हैं — उनकी स्थिति मिल जाती है। ESLint नियम hooks/exhaustive-deps इस के बारे में चेतावनी देता है।
useLayoutEffect सिंक्रोनस है और ब्राउज़र बदलावों को पेंट करने से पहले चलता है। useEffect असिंक्रोनस है — पेंटिंग के बाद। useLayoutEffect का उपयोग केवल तभी करें जब आपको उपयोगकर्ता के बदलाव देखने से पहले DOM को मापने या बदलने की आवश्यकता हो (popover स्थिति, स्क्रॉल बहाली).
useEffect के अंदर AbortController का उपयोग करें। एक controller बनाएँ, signal को fetch में पास करें, और cleanup फ़ंक्शन में controller.abort() कॉल करें। पुराने ब्राउज़र्स के लिए, एक cancelled फ़्लैग का उपयोग करें: return () => { cancelled = true; } setState से पहले एक जाँच के साथ।
कस्टम हुक एक JavaScript फ़ंक्शन है जिसका उपसर्ग use है जो बिल्ट-इन हुक का उपयोग करता है। इसे बनाएँ जब हुक के साथ वही तर्क दो या अधिक कंपोनेंट्स में दोहराया जाता है। उदाहरण: useDebounce, useLocalStorage, useMediaQuery। कस्टम हुक HOC और render props को बदलते हैं।
Strict Mode में, React जानबूझकर डिवेलपमेंट में असफा की गई प्रतिक्रियाओं के साथ बग्स खोजने के लिए कंपोनेंट को दो बार मौंट और अनमौंट करता है। यदि cleanup सही ढंग से लिखा गया है, तो दोहरा कॉल कोई समस्या नहीं पैदा करता। प्रोडक्शन मोड में ऐसा नहीं होता।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें