रिएक्ट createPortal API का एक व्यापक गाइड, जिसमें पोर्टल निर्माण, इवेंट हैंडलिंग और लचीले व सुलभ UI बनाने के लिए उन्नत उपयोग के मामले शामिल हैं।
रिएक्ट createPortal: पोर्टल निर्माण और इवेंट हैंडलिंग में महारत हासिल करना
रिएक्ट के साथ आधुनिक वेब डेवलपमेंट में, ऐसे यूजर इंटरफेस बनाना महत्वपूर्ण है जो अंतर्निहित डॉक्यूमेंट संरचना के साथ सहजता से एकीकृत हों। जबकि रिएक्ट का कंपोनेंट मॉडल वर्चुअल DOM को प्रबंधित करने में उत्कृष्ट है, कभी-कभी हमें सामान्य कंपोनेंट पदानुक्रम के बाहर तत्वों को रेंडर करने की आवश्यकता होती है। यहीं पर createPortal काम आता है। यह गाइड createPortal को गहराई से समझाता है, जिसमें इसके उद्देश्य, उपयोग और घटनाओं को संभालने और जटिल UI तत्वों के निर्माण के लिए उन्नत तकनीकों को शामिल किया गया है। हम अंतर्राष्ट्रीयकरण संबंधी विचारों, एक्सेसिबिलिटी सर्वोत्तम प्रथाओं और बचने योग्य सामान्य गलतियों को कवर करेंगे।
रिएक्ट createPortal क्या है?
createPortal एक रिएक्ट एपीआई है जो आपको रिएक्ट कंपोनेंट के चिल्ड्रन को DOM ट्री के एक अलग हिस्से में, पैरेंट कंपोनेंट के पदानुक्रम के बाहर रेंडर करने की अनुमति देता है। यह विशेष रूप से मॉडल्स, टूलटिप्स, ड्रॉपडाउन्स और ओवरले जैसे तत्वों को बनाने के लिए उपयोगी है, जिन्हें डॉक्यूमेंट के शीर्ष स्तर पर या एक विशिष्ट कंटेनर के भीतर स्थित करने की आवश्यकता होती है, भले ही उन्हें ट्रिगर करने वाला कंपोनेंट रिएक्ट कंपोनेंट ट्री में कहीं भी स्थित हो।
createPortal के बिना, इसे प्राप्त करने में अक्सर जटिल समाधान शामिल होते हैं जैसे कि DOM को सीधे बदलना या CSS एब्सोल्यूट पोजिशनिंग का उपयोग करना, जिससे स्टैकिंग कॉन्टेक्स्ट, z-इंडेक्स टकराव और एक्सेसिबिलिटी के साथ समस्याएं हो सकती हैं।
createPortal का उपयोग क्यों करें?
यहाँ मुख्य कारण दिए गए हैं कि क्यों createPortal आपके रिएक्ट शस्त्रागार में एक मूल्यवान उपकरण है:
- बेहतर DOM संरचना: DOM के भीतर कंपोनेंट्स को गहराई से नेस्ट करने से बचाता है, जिससे एक स्वच्छ और अधिक प्रबंधनीय संरचना बनती है। यह विशेष रूप से कई इंटरैक्टिव तत्वों वाले जटिल अनुप्रयोगों के लिए महत्वपूर्ण है।
- सरल स्टाइलिंग: जटिल CSS ट्रिक्स पर निर्भर हुए बिना व्यूपोर्ट या विशिष्ट कंटेनरों के सापेक्ष तत्वों को आसानी से पोजिशन करें। यह स्टाइलिंग और लेआउट को सरल बनाता है, खासकर उन तत्वों से निपटते समय जिन्हें अन्य सामग्री को ओवरले करने की आवश्यकता होती है।
- बढ़ी हुई एक्सेसिबिलिटी: कंपोनेंट पदानुक्रम से स्वतंत्र रूप से फोकस और कीबोर्ड नेविगेशन को प्रबंधित करने की अनुमति देकर सुलभ UI बनाने की सुविधा प्रदान करता है। उदाहरण के लिए, यह सुनिश्चित करना कि फोकस एक मॉडल विंडो के भीतर बना रहे।
- बेहतर इवेंट हैंडलिंग: घटनाओं को पोर्टल की सामग्री से रिएक्ट ट्री तक सही ढंग से प्रचारित करने की अनुमति देता है, यह सुनिश्चित करते हुए कि पैरेंट कंपोनेंट्स से जुड़े इवेंट श्रोता अभी भी अपेक्षा के अनुरूप काम करते हैं।
createPortal का मूल उपयोग
createPortal API दो आर्ग्यूमेंट्स स्वीकार करता है:
- वह रिएक्ट नोड (JSX) जिसे आप रेंडर करना चाहते हैं।
- वह DOM तत्व जहाँ आप नोड को रेंडर करना चाहते हैं। यह DOM तत्व आदर्श रूप से
createPortalका उपयोग करने वाले कंपोनेंट के माउंट होने से पहले मौजूद होना चाहिए।
यहाँ एक सरल उदाहरण है:
उदाहरण: एक मॉडल रेंडर करना
मान लीजिए आपके पास एक मॉडल कंपोनेंट है जिसे आप body तत्व के अंत में रेंडर करना चाहते हैं।
import React from 'react';
import ReactDOM from 'react-dom';
function Modal({ children, isOpen, onClose }) {
if (!isOpen) return null;
const modalRoot = document.getElementById('modal-root'); // Assumes you have a <div id="modal-root"></div> in your HTML
if (!modalRoot) {
console.error('Modal root element not found!');
return null;
}
return ReactDOM.createPortal(
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
{children}
</div>
</div>,
modalRoot
);
}
export default Modal;
व्याख्या:
- हम
ReactDOMइम्पोर्ट करते हैं क्योंकिcreatePortalReactDOMऑब्जेक्ट का एक मेथड है। - हम मानते हैं कि आपके HTML में
modal-rootआईडी वाला एक DOM तत्व है। यहीं पर मॉडल रेंडर किया जाएगा। सुनिश्चित करें कि यह तत्व मौजूद है। एक सामान्य अभ्यास यह है कि आप अपनीindex.htmlफ़ाइल में क्लोजिंग</body>टैग से ठीक पहले एक<div id="modal-root"></div>जोड़ें। - हम मॉडल के JSX को
modalRootतत्व में रेंडर करने के लिएReactDOM.createPortalका उपयोग करते हैं। - हम मॉडल सामग्री पर
onClickइवेंट को ओवरले परonCloseहैंडलर को ट्रिगर करने से रोकने के लिएe.stopPropagation()का उपयोग करते हैं। यह सुनिश्चित करता है कि मॉडल के अंदर क्लिक करने से वह बंद न हो।
उपयोग:
import React, { useState } from 'react';
import Modal from './Modal';
function App() {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<div>
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
<h2>Modal Content</h2>
<p>This is the content of the modal.</p>
<button onClick={() => setIsModalOpen(false)}>Close</button>
</Modal>
</div>
);
}
export default App;
यह उदाहरण दिखाता है कि सामान्य कंपोनेंट पदानुक्रम के बाहर एक मॉडल कैसे रेंडर किया जाए, जिससे आप इसे पृष्ठ पर बिल्कुल सही स्थिति में रख सकते हैं। इस तरह से createPortal का उपयोग करने से स्टैकिंग कॉन्टेक्स्ट के साथ आम समस्याएं हल होती हैं और आप अपने एप्लिकेशन में आसानी से सुसंगत मॉडल स्टाइलिंग बना सकते हैं।
createPortal के साथ इवेंट हैंडलिंग
createPortal के प्रमुख लाभों में से एक यह है कि यह रिएक्ट के सामान्य इवेंट बबलिंग व्यवहार को संरक्षित रखता है। इसका मतलब है कि पोर्टल की सामग्री के भीतर उत्पन्न होने वाली घटनाएँ अभी भी रिएक्ट कंपोनेंट ट्री में ऊपर की ओर प्रचारित होंगी, जिससे पैरेंट कंपोनेंट्स उन्हें संभाल सकेंगे।
हालाँकि, यह समझना महत्वपूर्ण है कि जब घटनाएँ पोर्टल की सीमा को पार करती हैं तो उन्हें कैसे संभाला जाता है।
उदाहरण: पोर्टल के बाहर की घटनाओं को संभालना
import React, { useState, useRef, useEffect } from 'react';
import ReactDOM from 'react-dom';
function OutsideClickExample() {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef(null);
const portalRoot = document.getElementById('portal-root');
useEffect(() => {
function handleClickOutside(event) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
setIsOpen(false);
}
}
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [dropdownRef]);
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>Toggle Dropdown</button>
{isOpen && portalRoot && ReactDOM.createPortal(
<div ref={dropdownRef} style={{ position: 'absolute', top: '50px', left: '0', border: '1px solid black', padding: '10px', backgroundColor: 'white' }}>
Dropdown Content
</div>,
portalRoot
)}
</div>
);
}
export default OutsideClickExample;
व्याख्या:
- हम पोर्टल के अंदर रेंडर किए गए ड्रॉपडाउन तत्व तक पहुंचने के लिए एक
refका उपयोग करते हैं। - हम ड्रॉपडाउन के बाहर क्लिक का पता लगाने के लिए
documentमें एकmousedownइवेंट लिसनर जोड़ते हैं। - इवेंट लिसनर के अंदर, हम यह जांचते हैं कि क्लिक ड्रॉपडाउन के बाहर हुआ है या नहीं, इसके लिए
dropdownRef.current.contains(event.target)का उपयोग करते हैं। - यदि क्लिक ड्रॉपडाउन के बाहर हुआ है, तो हम
isOpenकोfalseपर सेट करके इसे बंद कर देते हैं।
यह उदाहरण दिखाता है कि पोर्टल की सामग्री के बाहर होने वाली घटनाओं को कैसे संभाला जाए, जिससे आप ऐसे इंटरैक्टिव तत्व बना सकते हैं जो आसपास के डॉक्यूमेंट में उपयोगकर्ता की कार्रवाइयों पर प्रतिक्रिया करते हैं।
उन्नत उपयोग के मामले
createPortal केवल साधारण मॉडल्स और टूलटिप्स तक ही सीमित नहीं है। इसका उपयोग विभिन्न उन्नत परिदृश्यों में किया जा सकता है, जिनमें शामिल हैं:
- संदर्भ मेनू (Context Menus): राइट-क्लिक पर माउस कर्सर के पास गतिशील रूप से संदर्भ मेनू रेंडर करें।
- सूचनाएं (Notifications): कंपोनेंट पदानुक्रम की परवाह किए बिना स्क्रीन के शीर्ष पर सूचनाएं प्रदर्शित करें।
- कस्टम पॉपओवर (Custom Popovers): उन्नत पोजिशनिंग और स्टाइलिंग के साथ कस्टम पॉपओवर कंपोनेंट बनाएं।
- तृतीय-पक्ष पुस्तकालयों के साथ एकीकरण: रिएक्ट कंपोनेंट्स को तृतीय-पक्ष पुस्तकालयों के साथ एकीकृत करने के लिए
createPortalका उपयोग करें, जिन्हें विशिष्ट DOM संरचनाओं की आवश्यकता होती है।
उदाहरण: एक संदर्भ मेनू बनाना
import React, { useState, useRef, useEffect } from 'react';
import ReactDOM from 'react-dom';
function ContextMenuExample() {
const [contextMenu, setContextMenu] = useState(null);
const menuRef = useRef(null);
useEffect(() => {
function handleClickOutside(event) {
if (menuRef.current && !menuRef.current.contains(event.target)) {
setContextMenu(null);
}
}
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [menuRef]);
const handleContextMenu = (event) => {
event.preventDefault();
setContextMenu({
x: event.clientX,
y: event.clientY,
});
};
const portalRoot = document.getElementById('portal-root');
return (
<div onContextMenu={handleContextMenu} style={{ border: '1px solid black', padding: '20px' }}>
Right-click here to open context menu
{contextMenu && portalRoot && ReactDOM.createPortal(
<div
ref={menuRef}
style={{
position: 'absolute',
top: contextMenu.y,
left: contextMenu.x,
border: '1px solid black',
padding: '10px',
backgroundColor: 'white',
}}
>
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
</div>,
portalRoot
)}
</div>
);
}
export default ContextMenuExample;
व्याख्या:
- हम लक्ष्य तत्व पर राइट-क्लिक का पता लगाने के लिए
onContextMenuइवेंट का उपयोग करते हैं। - हम
event.preventDefault()का उपयोग करके डिफ़ॉल्ट संदर्भ मेनू को दिखने से रोकते हैं। - हम माउस निर्देशांक को
contextMenuस्टेट वेरिएबल में संग्रहीत करते हैं। - हम संदर्भ मेनू को एक पोर्टल के अंदर रेंडर करते हैं, जिसे माउस निर्देशांक पर स्थित किया गया है।
- हम पिछले उदाहरण की तरह ही बाहर-क्लिक का पता लगाने वाले लॉजिक को शामिल करते हैं ताकि जब उपयोगकर्ता इसके बाहर क्लिक करे तो संदर्भ मेनू बंद हो जाए।
एक्सेसिबिलिटी संबंधी विचार
createPortal का उपयोग करते समय, यह सुनिश्चित करने के लिए एक्सेसिबिलिटी पर विचार करना महत्वपूर्ण है कि आपका एप्लिकेशन सभी के लिए प्रयोग करने योग्य हो।
फोकस प्रबंधन
जब कोई पोर्टल खुलता है (जैसे, एक मॉडल), तो आपको यह सुनिश्चित करना चाहिए कि फोकस स्वचालित रूप से पोर्टल के भीतर पहले इंटरैक्टिव तत्व पर चला जाए। यह उन उपयोगकर्ताओं की मदद करता है जो कीबोर्ड या स्क्रीन रीडर से नेविगेट करते हैं ताकि वे पोर्टल की सामग्री तक आसानी से पहुंच सकें।
जब पोर्टल बंद हो जाता है, तो आपको उस तत्व पर फोकस वापस करना चाहिए जिसने पोर्टल के खुलने को ट्रिगर किया था। यह एक सुसंगत नेविगेशन प्रवाह बनाए रखता है।
ARIA एट्रिब्यूट्स
पोर्टल की सामग्री के बारे में सिमेंटिक जानकारी प्रदान करने के लिए ARIA एट्रिब्यूट्स का उपयोग करें। उदाहरण के लिए, मॉडल तत्व पर aria-modal="true" का उपयोग करें यह इंगित करने के लिए कि यह एक मॉडल डायलॉग है। मॉडल को उसके शीर्षक के साथ जोड़ने के लिए aria-labelledby का उपयोग करें, और इसे उसके विवरण के साथ जोड़ने के लिए aria-describedby का उपयोग करें।
कीबोर्ड नेविगेशन
सुनिश्चित करें कि उपयोगकर्ता कीबोर्ड का उपयोग करके पोर्टल की सामग्री को नेविगेट कर सकते हैं। फोकस क्रम को नियंत्रित करने के लिए tabindex एट्रिब्यूट का उपयोग करें, और सुनिश्चित करें कि सभी इंटरैक्टिव तत्व कीबोर्ड से पहुंच योग्य हैं।
पोर्टल के भीतर फोकस को ट्रैप करने पर विचार करें ताकि उपयोगकर्ता गलती से इसके बाहर नेविगेट न कर सकें। यह Tab कुंजी को सुनकर और प्रोग्रामेटिक रूप से पोर्टल के भीतर पहले या अंतिम इंटरैक्टिव तत्व पर फोकस ले जाकर प्राप्त किया जा सकता है।
उदाहरण: सुलभ मॉडल
import React, { useState, useRef, useEffect } from 'react';
import ReactDOM from 'react-dom';
function AccessibleModal({ children, isOpen, onClose, labelledBy, describedBy }) {
const modalRef = useRef(null);
const firstFocusableElementRef = useRef(null);
const [previouslyFocusedElement, setPreviouslyFocusedElement] = useState(null);
const modalRoot = document.getElementById('modal-root');
useEffect(() => {
if (isOpen) {
// Save the currently focused element before opening the modal.
setPreviouslyFocusedElement(document.activeElement);
// Focus the first focusable element in the modal.
if (firstFocusableElementRef.current) {
firstFocusableElementRef.current.focus();
}
// Trap focus within the modal.
function handleKeyDown(event) {
if (event.key === 'Tab') {
const focusableElements = modalRef.current.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstFocusableElement = focusableElements[0];
const lastFocusableElement = focusableElements[focusableElements.length - 1];
if (event.shiftKey) {
// Shift + Tab
if (document.activeElement === firstFocusableElement) {
lastFocusableElement.focus();
event.preventDefault();
}
} else {
// Tab
if (document.activeElement === lastFocusableElement) {
firstFocusableElement.focus();
event.preventDefault();
}
}
}
}
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
// Restore focus to the element that had focus before opening the modal.
if(previouslyFocusedElement && previouslyFocusedElement.focus) {
previouslyFocusedElement.focus();
}
};
}
}, [isOpen, previouslyFocusedElement]);
if (!isOpen) return null;
return ReactDOM.createPortal(
<div
className="modal-overlay"
onClick={onClose}
aria-modal="true"
aria-labelledby={labelledBy}
aria-describedby={describedBy}
ref={modalRef}
>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<h2 id={labelledBy}>Modal Title</h2>
<p id={describedBy}>This is the modal content.</p>
<button ref={firstFocusableElementRef} onClick={onClose}>
Close
</button>
{children}
</div>
</div>,
modalRoot
);
}
export default AccessibleModal;
व्याख्या:
- हम मॉडल के बारे में सिमेंटिक जानकारी प्रदान करने के लिए
aria-modal,aria-labelledby, औरaria-describedbyजैसे ARIA एट्रिब्यूट्स का उपयोग करते हैं। - जब मॉडल खुलता और बंद होता है तो हम फोकस को प्रबंधित करने के लिए
useEffectहुक का उपयोग करते हैं। - हम मॉडल खोलने से पहले वर्तमान में फोकस्ड तत्व को सहेजते हैं और मॉडल बंद होने पर उस पर फोकस बहाल करते हैं।
- हम
keydownइवेंट लिसनर का उपयोग करके मॉडल के भीतर फोकस को ट्रैप करते हैं।
अंतर्राष्ट्रीयकरण (i18n) संबंधी विचार
वैश्विक दर्शकों के लिए एप्लिकेशन विकसित करते समय, अंतर्राष्ट्रीयकरण (i18n) एक महत्वपूर्ण विचार है। createPortal का उपयोग करते समय, कुछ बातों का ध्यान रखना चाहिए:
- पाठ दिशा (RTL/LTR): सुनिश्चित करें कि आपकी स्टाइलिंग बाएँ-से-दाएँ (LTR) और दाएँ-से-बाएँ (RTL) दोनों भाषाओं को समायोजित करती है। इसमें CSS में लॉजिकल गुणों का उपयोग करना (जैसे,
margin-leftके बजायmargin-inline-start) और HTML तत्व परdirएट्रिब्यूट को उचित रूप से सेट करना शामिल हो सकता है। - सामग्री का स्थानीयकरण: पोर्टल के भीतर सभी पाठ को उपयोगकर्ता की पसंदीदा भाषा में स्थानीयकृत किया जाना चाहिए। अनुवादों को प्रबंधित करने के लिए एक i18n लाइब्रेरी (जैसे,
react-intl,i18next) का उपयोग करें। - संख्या और दिनांक स्वरूपण: उपयोगकर्ता के लोकेल के अनुसार संख्याओं और दिनांकों को प्रारूपित करें।
IntlAPI इसके लिए कार्यक्षमता प्रदान करता है। - सांस्कृतिक परंपराएं: UI तत्वों से संबंधित सांस्कृतिक परंपराओं से अवगत रहें। उदाहरण के लिए, बटन प्लेसमेंट संस्कृतियों में भिन्न हो सकता है।
उदाहरण: react-intl के साथ i18n
import React from 'react';
import { FormattedMessage } from 'react-intl';
function MyComponent() {
return (
<div>
<FormattedMessage id="myComponent.greeting" defaultMessage="Hello, world!" />
</div>
);
}
export default MyComponent;
react-intl से FormattedMessage कंपोनेंट उपयोगकर्ता के लोकेल के आधार पर अनुवादित संदेश प्राप्त करता है। विभिन्न भाषाओं के लिए अपने अनुवादों के साथ react-intl को कॉन्फ़िगर करें।
सामान्य गलतियाँ और समाधान
जबकि createPortal एक शक्तिशाली उपकरण है, कुछ सामान्य गलतियों और उनसे बचने के तरीकों से अवगत रहना महत्वपूर्ण है:
- पोर्टल रूट तत्व का न होना: सुनिश्चित करें कि जिस DOM तत्व को आप पोर्टल रूट के रूप में उपयोग कर रहे हैं, वह
createPortalका उपयोग करने वाले कंपोनेंट के माउंट होने से पहले मौजूद हो। एक अच्छा अभ्यास यह है कि इसे सीधेindex.htmlमें रखा जाए। - Z-इंडेक्स टकराव:
createPortalके साथ तत्वों को पोजिशन करते समय z-इंडेक्स मानों का ध्यान रखें। स्टैकिंग कॉन्टेक्स्ट को प्रबंधित करने के लिए CSS का उपयोग करें और सुनिश्चित करें कि आपके पोर्टल की सामग्री सही ढंग से प्रदर्शित हो। - इवेंट हैंडलिंग समस्याएं: समझें कि घटनाएँ पोर्टल के माध्यम से कैसे प्रचारित होती हैं और उन्हें उचित रूप से संभालें। घटनाओं को अनपेक्षित क्रियाओं को ट्रिगर करने से रोकने के लिए
e.stopPropagation()का उपयोग करें। - मेमोरी लीक: मेमोरी लीक से बचने के लिए जब
createPortalका उपयोग करने वाला कंपोनेंट अनमाउंट हो जाए तो इवेंट लिसनर्स और रेफरेंस को ठीक से साफ़ करें। इसे प्राप्त करने के लिए क्लीनअप फ़ंक्शन के साथuseEffectहुक का उपयोग करें। - अप्रत्याशित स्क्रॉलिंग समस्याएं: पोर्टल कभी-कभी पृष्ठ के अपेक्षित स्क्रॉलिंग व्यवहार में हस्तक्षेप कर सकते हैं। सुनिश्चित करें कि आपकी स्टाइल स्क्रॉलिंग को नहीं रोक रही हैं और मॉडल तत्व खुलने और बंद होने पर पृष्ठ में उछाल या अप्रत्याशित स्क्रॉलिंग व्यवहार का कारण नहीं बनते हैं।
निष्कर्ष
React.createPortal रिएक्ट में लचीले, सुलभ और रखरखाव योग्य UI बनाने के लिए एक मूल्यवान उपकरण है। इसके उद्देश्य, उपयोग और घटनाओं तथा एक्सेसिबिलिटी को संभालने के लिए उन्नत तकनीकों को समझकर, आप जटिल और आकर्षक वेब एप्लिकेशन बनाने के लिए इसकी शक्ति का लाभ उठा सकते हैं जो वैश्विक दर्शकों के लिए एक बेहतर उपयोगकर्ता अनुभव प्रदान करते हैं। यह सुनिश्चित करने के लिए कि आपके एप्लिकेशन समावेशी और सभी के लिए प्रयोग करने योग्य हों, अंतर्राष्ट्रीयकरण और एक्सेसिबिलिटी की सर्वोत्तम प्रथाओं पर विचार करना याद रखें।
इस गाइड में दिए गए दिशानिर्देशों और उदाहरणों का पालन करके, आप सामान्य UI चुनौतियों को हल करने और आश्चर्यजनक वेब अनुभव बनाने के लिए आत्मविश्वास से createPortal का उपयोग कर सकते हैं।