Events पर प्रतिक्रिया देना
React आपको अपने JSX में event handler डालने की सुविधा देता है। Event handler आपकी स्वयं की फंक्शन्स होती हैं, जिन्हें क्लिक करना, होवर करना, फॉर्म इनपुट्स को फोकस करना आदि जैसी इंटरैक्शंस पर प्रतिक्रिया स्वरूप ट्रिगर किया जाता है।
You will learn
- Event handler लिखने के विभिन्न तरीके
- पैरेंट कौम्पोनॅन्ट से event handling लॉजिक को पास करने का तरीका
- Events का प्रचार कैसे होता है और इसे कैसे रोका जा सकता है
Event handler ऐड करना
Event handler ऐड करने के लिए, पहले एक फंक्शन को परिभाषित करें और फिर उसे props के रूप में पास करें उपयुक्त JSX टैग में। उदाहरण के लिए, यहाँ एक बटन है जो अभी कुछ नहीं करता है:
export default function Button() { return ( <button> I don't do anything </button> ); }
आप यूजर द्वारा क्लिक करने पर संदेश दिखाने के लिए निम्न तीन चरणों का पालन कर सकते हैं:
- अपने
Button
कौम्पोनॅन्ट के अंदरhandleClick
नाम का एक फंक्शन डिक्लेअर करें। - उस फंक्शन के अंदर लॉजिक को लागू करें (संदेश दिखाने के लिए
alert
का उपयोग करें)। <button>
JSX मेंonClick={handleClick}
जोड़ें।
export default function Button() { function handleClick() { alert('You clicked me!'); } return ( <button onClick={handleClick}> Click me </button> ); }
आपने handleClick
फंक्शन को परिभाषित किया और फिर इसे props के रूप में पास किया <button>
में। handleClick
एक event handler है। Event हैंडलर फंक्शन्स:
- आमतौर पर अंदर आपके कौम्पोनॅन्ट्स के परिभाषित होते हैं।
- उनके नाम
handle
से शुरू होते हैं, इसके बाद event का नाम आता है।
परंपरा के अनुसार, event handlers को handle
और event के नाम के बाद नामित करना सामान्य है। आप अक्सर onClick={handleClick}
, onMouseEnter={handleMouseEnter}
, आदि देखते हैं।
वैकल्पिक रूप से, आप JSX में event handler को इनलाइन भी परिभाषित कर सकते हैं:
<button onClick={function handleClick() {
alert('You clicked me!');
}}>
या, अधिक संक्षेप में, एरो फंक्शन का उपयोग करते हुए:
<button onClick={() => {
alert('You clicked me!');
}}>
इन सभी स्टाइल्स समकक्ष हैं। इनलाइन event handlers छोटे फंक्शन्स के लिए सुविधाजनक होते हैं।
Event हैंडलर्स में props को पढ़ना
चूंकि event हैंडलर कौम्पोनॅन्ट के अंदर परिभाषित होते हैं, उन्हें कौम्पोनॅन्ट की props तक पहुंच प्राप्त होती है। यहाँ एक बटन है, जो क्लिक होने पर अपनी message
props के साथ एक अलर्ट दिखाता है:
function AlertButton({ message, children }) { return ( <button onClick={() => alert(message)}> {children} </button> ); } export default function Toolbar() { return ( <div> <AlertButton message="Playing!"> Play Movie </AlertButton> <AlertButton message="Uploading!"> Upload Image </AlertButton> </div> ); }
यह इन दो बटनों को अलग-अलग संदेश दिखाने देता है। उनके पास किए गए संदेशों को बदलकर देखें।
Event हैंडलर्स को props के रूप में पास करना
अक्सर आपको पैरेंट कौम्पोनॅन्ट को बच्चे के event हैंडलर को निर्दिष्ट करने की आवश्यकता होती है। बटनों पर विचार करें: जिस स्थान पर आप Button
कौम्पोनॅन्ट का उपयोग कर रहे हैं, वहां आप एक अलग फंक्शन चलाना चाह सकते हैं—शायद एक फिल्म चलाता है और दूसरा इमेज अपलोड करता है।
इसके लिए, उस event हैंडलर के रूप में props को पास करें जो कौम्पोनॅन्ट अपने पैरेंट से प्राप्त करता है, जैसे कि:
function Button({ onClick, children }) { return ( <button onClick={onClick}> {children} </button> ); } function PlayButton({ movieName }) { function handlePlayClick() { alert(`Playing ${movieName}!`); } return ( <Button onClick={handlePlayClick}> Play "{movieName}" </Button> ); } function UploadButton() { return ( <Button onClick={() => alert('Uploading!')}> Upload Image </Button> ); } export default function Toolbar() { return ( <div> <PlayButton movieName="Kiki's Delivery Service" /> <UploadButton /> </div> ); }
यहाँ, Toolbar
कौम्पोनॅन्ट एक PlayButton
और एक UploadButton
रेंडर करता है:
PlayButton
handlePlayClick
कोonClick
props के रूप मेंButton
को पास करता है।UploadButton
() => alert('Uploading!')
कोonClick
prop के रूप मेंButton
को पास करता है।
अंत में, आपका Button
कौम्पोनॅन्ट एक prop स्वीकार करता है जिसे onClick
कहा जाता है। यह prop को सीधे बिल्ट-इन ब्राउज़र <button>
में onClick={onClick}
के साथ पास करता है। यह React को यह बताता है कि क्लिक पर पास किया गया फंक्शन कॉल किया जाए।
यदि आप डिज़ाइन सिस्टम का उपयोग करते हैं, तो यह सामान्य है कि बटनों जैसे कौम्पोनॅन्ट्स में स्टाइलिंग होती है लेकिन व्यवहार निर्दिष्ट नहीं होता। इसके बजाय, PlayButton
और UploadButton
जैसे कौम्पोनॅन्ट्स event हैंडलर्स को पास करेंगे।
Event हैंडलर props का नामकरण
बिल्ट-इन कौम्पोनॅन्ट्स जैसे <button>
और <div>
केवल ब्राउज़र event नामों का समर्थन करते हैं जैसे onClick
। हालांकि, जब आप अपने खुद के कौम्पोनॅन्ट्स बना रहे होते हैं, तो आप उनके event हैंडलर props का नाम किसी भी तरीके से रख सकते हैं जो आपको पसंद हो।
परंपरा के अनुसार, event हैंडलर props को on
से शुरू करना चाहिए, इसके बाद एक बड़ा अक्षर होना चाहिए।
उदाहरण के लिए, Button
कौम्पोनॅन्ट के onClick
prop को onSmash
भी कहा जा सकता था:
function Button({ onSmash, children }) { return ( <button onClick={onSmash}> {children} </button> ); } export default function App() { return ( <div> <Button onSmash={() => alert('Playing!')}> Play Movie </Button> <Button onSmash={() => alert('Uploading!')}> Upload Image </Button> </div> ); }
इस उदाहरण में, <button onClick={onSmash}>
यह दिखाता है कि ब्राउज़र <button>
(लोअरकेस) को अभी भी onClick
नामक prop की आवश्यकता होती है, लेकिन आपकी कस्टम Button
कौम्पोनॅन्ट द्वारा प्राप्त prop का नाम आपके ऊपर है!
जब आपका कौम्पोनॅन्ट कई इंटरएक्शन्स का समर्थन करता है, तो आप event हैंडलर props को ऐप-स्पेसिफिक अवधारणाओं के लिए नाम दे सकते हैं। उदाहरण के लिए, यह Toolbar
कौम्पोनॅन्ट onPlayMovie
और onUploadImage
event हैंडलर्स प्राप्त करता है:
export default function App() { return ( <Toolbar onPlayMovie={() => alert('Playing!')} onUploadImage={() => alert('Uploading!')} /> ); } function Toolbar({ onPlayMovie, onUploadImage }) { return ( <div> <Button onClick={onPlayMovie}> Play Movie </Button> <Button onClick={onUploadImage}> Upload Image </Button> </div> ); } function Button({ onClick, children }) { return ( <button onClick={onClick}> {children} </button> ); }
ध्यान दें कि App
कौम्पोनॅन्ट को यह जानने की आवश्यकता नहीं है कि Toolbar
onPlayMovie
या onUploadImage
के साथ क्या करेगा। यह Toolbar
का एक कार्यान्वयन विवरण है। यहाँ, Toolbar
इन्हें onClick
हैंडलर्स के रूप में अपने Button
कौम्पोनॅन्ट्स को पास करता है, लेकिन बाद में इसे कीबोर्ड शॉर्टकट पर भी ट्रिगर किया जा सकता है। ऐप-स्पेसिफिक इंटरएक्शन्स जैसे onPlayMovie
के आधार पर props का नामकरण आपको लचीलापन देता है कि आप बाद में इनका उपयोग कैसे करें।
Event प्रचारण
Event handler आपके कौम्पोनॅन्ट के किसी भी बच्चे से event को भी पकड़ेंगे। हम कहते हैं कि एक event “बबल्स” या “प्रचारित” होती है: यह उस स्थान से शुरू होती है जहाँ event हुआ था, और फिर पेड़ (ट्री) में ऊपर की ओर जाती है।
यह <div>
दो बटनों को शामिल करता है। <div>
और प्रत्येक बटन के अपने-अपने onClick
हैंडलर्स होते हैं। क्या आपको लगता है कि जब आप बटन पर क्लिक करेंगे, तो कौन से हैंडलर्स फायर होंगे?
export default function Toolbar() { return ( <div className="Toolbar" onClick={() => { alert('You clicked on the toolbar!'); }}> <button onClick={() => alert('Playing!')}> Play Movie </button> <button onClick={() => alert('Uploading!')}> Upload Image </button> </div> ); }
यदि आप किसी भी बटन पर क्लिक करते हैं, तो उसका onClick
पहले चलेगा, फिर पैरेंट <div>
का onClick
चलेगा। इसलिए दो संदेश दिखाई देंगे। अगर आप स्वयं टूलबार पर क्लिक करते हैं, तो केवल पैरेंट <div>
का onClick
चलेगा।
प्रचारण को रोकना
Event handler एक event ऑब्जेक्ट को अपने एकमात्र आर्ग्युमेंट के रूप में प्राप्त करते हैं। परंपरा के अनुसार, इसे आमतौर पर e
कहा जाता है, जो “event” के लिए खड़ा है। आप इस ऑब्जेक्ट का उपयोग event के बारे में जानकारी पढ़ने के लिए कर सकते हैं।
यह event ऑब्जेक्ट आपको प्रचारण को रोकने की भी अनुमति देता है। यदि आप किसी event को पैरेंट कौम्पोनॅन्ट्स तक पहुँचने से रोकना चाहते हैं, तो आपको e.stopPropagation()
कॉल करना होगा, जैसे कि यह Button
कौम्पोनॅन्ट करता है:
function Button({ onClick, children }) { return ( <button onClick={e => { e.stopPropagation(); onClick(); }}> {children} </button> ); } export default function Toolbar() { return ( <div className="Toolbar" onClick={() => { alert('You clicked on the toolbar!'); }}> <Button onClick={() => alert('Playing!')}> Play Movie </Button> <Button onClick={() => alert('Uploading!')}> Upload Image </Button> </div> ); }
जब आप किसी बटन पर क्लिक करते हैं:
- React
<button>
को पास किए गएonClick
हैंडलर को कॉल करता है। - वह हैंडलर, जो
Button
में परिभाषित है, निम्नलिखित करता है:e.stopPropagation()
को कॉल करता है, जिससे event का बबलिंग आगे नहीं बढ़ता।onClick
फंक्शन को कॉल करता है, जोToolbar
कौम्पोनॅन्ट से पास की गई एक prop है।
- वह फंक्शन, जो
Toolbar
कौम्पोनॅन्ट में परिभाषित है, बटन का अपना अलर्ट दिखाता है। - चूंकि प्रचारण को रोका गया था, पैरेंट
<div>
काonClick
हैंडलर नहीं चलेगा।
e.stopPropagation()
के परिणामस्वरूप, बटन पर क्लिक करने से अब केवल एक ही अलर्ट (जो <button>
से आता है) दिखाई देता है, न कि दोनों (जो <button>
और पैरेंट टूलबार <div>
से आते थे)। बटन पर क्लिक करना और आसपास के टूलबार पर क्लिक करना एक जैसा नहीं है, इसलिए प्रचारण को रोकना इस UI के लिए उचित है।
Deep Dive
कभी-कभी, आपको बच्चों के तत्वों पर सभी events को पकड़ने की आवश्यकता हो सकती है, यहाँ तक कि अगर उन्होंने प्रचारण को रोक दिया हो। उदाहरण के लिए, हो सकता है कि आप हर क्लिक को एनालिटिक्स में लॉग करना चाहते हों, चाहे प्रचारण लॉजिक कुछ भी हो। आप यह Capture
को event नाम के अंत में जोड़कर कर सकते हैं:
<div onClickCapture={() => { /* this runs first */ }}>
<button onClick={e => e.stopPropagation()} />
<button onClick={e => e.stopPropagation()} />
</div>
प्रत्येक event तीन चरणों में प्रचारित होता है:
- यह नीचे की ओर यात्रा करता है, सभी
onClickCapture
हैंडलर्स को कॉल करता है। - यह क्लिक किए गए तत्व का
onClick
हैंडलर चलाता है। - यह ऊपर की ओर यात्रा करता है, सभी
onClick
हैंडलर्स को कॉल करता है।
कैप्चर events राउटर्स या एनालिटिक्स जैसे कोड के लिए उपयोगी होते हैं, लेकिन आप इन्हें ऐप कोड में शायद ही कभी उपयोग करेंगे।
प्रचारण के विकल्प के रूप में हैंडलर्स को पास करना
ध्यान दें कि कैसे यह क्लिक हैंडलर एक लाइन का कोड चलाता है और फिर पैरेंट द्वारा पास किए गए onClick
prop को कॉल करता है:
function Button({ onClick, children }) {
return (
<button onClick={e => {
e.stopPropagation();
onClick();
}}>
{children}
</button>
);
}
आप इस हैंडलर में पैरेंट के onClick
event handler को कॉल करने से पहले और भी कोड जोड़ सकते हैं। यह पैटर्न प्रचारण का एक विकल्प प्रदान करता है। यह बच्चे के कौम्पोनॅन्ट को event को संभालने देता है, जबकि पैरेंट कौम्पोनॅन्ट को कुछ अतिरिक्त व्यवहार निर्दिष्ट करने की अनुमति देता है। प्रचारण के विपरीत, यह स्वचालित नहीं होता है। लेकिन इस पैटर्न का लाभ यह है कि आप उस पूरी कोड चेन को स्पष्ट रूप से देख सकते हैं जो किसी event के परिणामस्वरूप निष्पादित होती है।
अगर आप प्रचारण पर निर्भर हैं और यह ट्रेस करना मुश्किल हो कि कौन से हैंडलर्स निष्पादित होते हैं और क्यों, तो इसके बजाय यह तरीका आजमाएं।
डिफ़ॉल्ट व्यवहार को रोकना
कुछ ब्राउज़र events के साथ डिफ़ॉल्ट व्यवहार जुड़ा होता है। उदाहरण के लिए, एक <form>
सबमिट event, जो तब होता है जब इसके अंदर एक बटन पर क्लिक किया जाता है, डिफ़ॉल्ट रूप से पूरी पेज को रीलोड कर देता है:
export default function Signup() { return ( <form onSubmit={() => alert('Submitting!')}> <input /> <button>Send</button> </form> ); }
आप e.preventDefault()
को event ऑब्जेक्ट पर कॉल कर सकते हैं ताकि इस प्रक्रिया को रुकवाया जा सके:
export default function Signup() { return ( <form onSubmit={e => { e.preventDefault(); alert('Submitting!'); }}> <input /> <button>Send</button> </form> ); }
e.stopPropagation()
और e.preventDefault()
को भ्रमित न करें। ये दोनों उपयोगी होते हैं, लेकिन अप्रत्याशित होते हैं:
e.stopPropagation()
event handler को ऊपर के टैग्स से फायर होने से रोकता है।e.preventDefault()
कुछ events के लिए डिफ़ॉल्ट ब्राउज़र व्यवहार को रोकता है जिनके पास यह व्यवहार होता है।
क्या event handlers में साइड इफेक्ट्स हो सकते हैं?
बिल्कुल! event handlers साइड इफेक्ट्स के लिए सबसे अच्छा स्थान होते हैं।
रेंडरिंग फंक्शन्स के विपरीत, event handlers को प्योर होने की आवश्यकता नहीं होती, इसलिए यह कुछ बदलने के लिए एक बेहतरीन स्थान है—उदाहरण के लिए, टाइपिंग के जवाब में इनपुट के मान को बदलना, या बटन दबाने पर सूची को बदलना। हालांकि, कुछ जानकारी बदलने के लिए, आपको पहले इसे स्टोर करने का कोई तरीका चाहिए। React में, यह state, एक कौम्पोनॅन्ट की मेमोरी का उपयोग करके किया जाता है। आप इसके बारे में अगली पेज पर सब कुछ सीखेंगे।
Recap
- आप events को एक फंक्शन को props के रूप में किसी एलिमेंट् जैसे
<button>
में पास करके हैंडल कर सकते हैं। - Event handlers को पास किया जाना चाहिए, न कि कॉल किया जाना चाहिए!
onClick={handleClick}
, न किonClick={handleClick()}
। - आप event handler फंक्शन को अलग से या इनलाइन परिभाषित कर सकते हैं।
- Event handler एक कौम्पोनॅन्ट के अंदर परिभाषित होते हैं, इसलिए ये props तक पहुंच सकते हैं।
- आप एक पैरेंट में event handler डिक्लेयर कर सकते हैं और इसे चाइल्ड को props के रूप में पास कर सकते हैं।
- आप अपने खुद के event handler props को ऐप्लिकेशन-विशिष्ट नामों के साथ परिभाषित कर सकते हैं।
- Events ऊपर की ओर प्रचारित होते हैं। इसे रोकने के लिए पहले आर्गुमेंट पर
e.stopPropagation()
कॉल करें। - Events के पास अवांछित डिफ़ॉल्ट ब्राउज़र व्यवहार हो सकता है। इसे रोकने के लिए
e.preventDefault()
कॉल करें। - एक चाइल्ड हैंडलर से event handler props को स्पष्ट रूप से कॉल करना प्रचारण के एक अच्छे विकल्प के रूप में काम करता है।
Challenge 1 of 2: एक event handler को ठीक करना
इस बटन पर क्लिक करने से पेज का बैकग्राउंड सफेद और काला के बीच स्विच होना चाहिए। हालांकि, जब आप इसे क्लिक करते हैं, तो कुछ भी नहीं होता। समस्या को ठीक करें। (चिंता न करें, handleClick
के अंदर की लॉजिक सही है—वह हिस्सा ठीक है।)
export default function LightSwitch() { function handleClick() { let bodyStyle = document.body.style; if (bodyStyle.backgroundColor === 'black') { bodyStyle.backgroundColor = 'white'; } else { bodyStyle.backgroundColor = 'black'; } } return ( <button onClick={handleClick()}> Toggle the lights </button> ); }