React Portals kya hain aur inhe modal, tooltip ke liye kaise use karein? Is Hindi guide me code examples ke sath step-by-step seekhein!
हैलो दोस्तों! जब हम ReactJS में काम करते हैं, तो कभी-न-कभी हमारे सामने एक ऐसी सिचुएशन ज़रूर आती है जहाँ CSS की वजह से हमारी रातों की नींद उड़ जाती है। मान लीजिए आप एक बहुत ही ख़ूबसूरत Modal, Dropdown, या Tooltip बना रहे हैं। सब कुछ बढ़िया चल रहा है, लेकिन अचानक आप देखते हैं कि आपका Modal अपने Parent Component के overflow: hidden या z-index की वजह से आधा कट रहा है या स्क्रीन के पीछे छिप रहा है।
आप CSS की प्रॉपर्टीज़ बदलते हैं, सर खुजलाते हैं, लेकिन बात नहीं बनती। ऐसे ही समय पर React के डेवलपर्स ने हमारे लिए एक जादुई दरवाज़ा खोला था, जिसे हम React Portals कहते हैं। चलिए, आज चाय की चुस्की के साथ बिल्कुल आसान भाषा में समझते हैं कि यह React Portals आखिर क्या बला है और इसे प्रोडक्शन-रेडी कोड में कैसे इस्तेमाल किया जाता है।
⚡ Quick Answer: React Portals ReactJS ka ek unique feature hain jo components ko HTML DOM hierarchy ke bahar kisi bhi doosre DOM node me render karne ki azadi deta hai. Iska primary use modals, tooltips aur dropdowns banane me hota hai taaki overflow aur z-index stacking issues ko aasani se solve kiya ja sake.
---
React Portals क्या हैं (What are React Portals)?
साधारण शब्दों में कहें तो, React Portals हमें अपने React components को उनके Default Parent DOM Tree से बाहर निकालकर, DOM (Document Object Model) के किसी भी दूसरे हिस्से में Render करने की सुविधा देते हैं।
आमतौर पर, जब आप React में कोई Component रेंडर करते हैं, तो वह अपने Parent Component के अंदर ही एक Nested Child बनकर HTML में दिखाई देता है। लेकिन Portal का इस्तेमाल करके, आप उस Component को React Component Tree में तो उसी जगह रख सकते हैं (जिससे State और Context का एक्सेस बना रहे), लेकिन HTML structure में उसे किसी बिल्कुल अलग जगह पर भेज सकते हैं (जैसे कि सीधे <body> के नीचे)।
इसके बारे में अधिक विस्तार से जानने के लिए आप React Portal Official Documentation भी पढ़ सकते हैं।
---
React Portals की ज़रूरत क्यों पड़ती है (Why do we need them)?
दोस्तों, इसे समझने के लिए एक क्लासिक वेब डिज़ाइनिंग की प्रॉब्लम को देखते हैं। मान लीजिए आपके पास एक Sidebar component है जिसकी CSS कुछ इस तरह है:
.sidebar {
width: 250px;
position: relative;
overflow: hidden; /* यहाँ असली विलेन छुपा है! */
}
अब इस Sidebar के अंदर आपने एक <ProfileTooltip /> component डाला है। जैसे ही यूजर प्रोफाइल पर होवर करता है, आप चाहते हैं कि Tooltip साइडबार से बाहर निकलकर स्क्रीन पर दिखे। लेकिन चूंकि Sidebar पर overflow: hidden लगा हुआ है, आपका Tooltip साइडबार की सीमाओं (borders) के अंदर ही कट जाएगा!
यही नहीं, कई बार z-index का ऐसा झंझट खड़ा होता है कि लाख कोशिशों के बाद भी आपका Modal बैकड्रॉप (overlay) के पीछे ही रह जाता है। इन सभी समस्याओं का एकमात्र और सबसे साफ़-सुथरा समाधान है React Portals। यह आपके Element को उठाकर सीधे Root DOM के समानांतर (parallel) खड़ा कर देता है, जिससे सारे CSS constraints खत्म हो जाते हैं।
---
React Portals कैसे काम करते हैं (How do they work)?
React Portals के पीछे का आर्किटेक्चर बहुत ही दिलचस्प है। यह React की वर्चुअल ट्री (React Tree) और असली ब्राउज़र ट्री (HTML DOM Tree) के बीच एक ब्रिज की तरह काम करता है।
🏗️ React Portals DOM Flow Architecture
App Root (#root)
Standard React Tree
⇢ (React Portal)
Portal Node (#portal-root)
Rendered Outside Parent CSS
Diagram: component logic stays in App Tree, but HTML renders in #portal-root node.
ध्यान देने वाली बात ये है कि भले ही आपका Component फिजिकल DOM में कहीं भी रेंडर हो रहा हो, वह React Tree के अंदर अपने पेरेंट के साथ ही जुड़ा रहता है। इसका मतलब है कि React Context API, custom hooks, और State Props वैसे ही काम करेंगे जैसे वे नॉर्मल Components के लिए करते हैं।
---
React Portals vs Normal Rendering में क्या अंतर है?
चलिए इन दोनों के अंतर को एक बार साफ़-साफ़ कंपैरिजन टेबल से समझ लेते हैं ताकि कोई कन्फ़्यूजन न रहे:
| फ़ीचर / अंतर | Normal Rendering | React Portals |
|---|---|---|
| DOM Insertion | Parent Component के अंदर ही nested होता है। | Target DOM Node (जैसे body) में बाहर रेंडर होता है। |
| CSS Isolation | Parent के overflow और z-index से प्रभावित होता है। |
Parent के CSS रूल्स से पूरी तरह आज़ाद रहता है। |
| Event Bubbling | नॉर्मल DOM के अनुसार ऊपर की तरफ बबल करता है। | React Tree के अनुसार ही बबल करता है, भले ही DOM स्ट्रक्चर अलग हो। |
| Best Used For | Regular UI Layouts (Buttons, Inputs, Cards). | Modals, Tooltips, Global Popups, Dropdowns. |
---
React Portals को Step-by-Step कैसे implement करें (With Code)?
अब कोडिंग का समय आ गया है! हम एक पूरी तरह से फंक्शनल, रेस्पॉन्सिव और खूबसूरत Modal Component बनाएंगे जो React Portals का इस्तेमाल करेगा।
Step 1: HTML फ़ाइल में Target Node बनाना
सबसे पहले, हमें अपने React App की मुख्य HTML फ़ाइल (आमतौर पर public/index.html या Vite प्रोजेक्ट्स में index.html) को खोलना है और वहाँ हमारे React Root Div के बिल्कुल नीचे एक नया Anchor Container बनाना है।
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Portal Modal Demo</title>
</head>
<body>
<div id="root"></div>
<div id="portal-root"></div>
</body>
</html>
Step 2: ReactDOM createPortal का Syntax समझना
React Portals बनाने के लिए हम react-dom पैकेज से createPortal मेथड का उपयोग करते हैं। इसका बेसिक सिंटैक्स कुछ ऐसा होता है:
import ReactDOM from 'react-dom';
ReactDOM.createPortal(child, containerInstance);
-
child: कोई भी रेंडर करने योग्य React Child (जैसे JSX, Element, Component, String या Array)। -
containerInstance: वह असली DOM एलिमेंट जहाँ आप इस Child को पहुँचाना चाहते हैं (जैसेdocument.getElementById('portal-root'))।
Step 3: reusable Modal Component बनाना
अब हम अपना Modal.jsx कंपोनेंट तैयार करेंगे। ध्यान दें कि हम इसे पूरी तरह से सेफ बनाने के लिए कुछ चेक भी लगाएंगे ताकि सर्वर-साइड रेंडरिंग (SSR) के समय कोई error न आए।
import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
// Modal component styles in JS for clean demo
const BACKDROP_STYLES = {
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.7)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1000,
};
const MODAL_STYLES = {
background: '#ffffff',
padding: '30px',
borderRadius: '12px',
boxShadow: '0 10px 25px rgba(0, 0, 0, 0.2)',
maxWidth: '500px',
width: '90%',
zIndex: 1001,
fontFamily: 'sans-serif',
};
const CLOSE_BUTTON_STYLES = {
marginTop: '20px',
padding: '10px 20px',
border: 'none',
background: '#ef4444',
color: 'white',
borderRadius: '6px',
cursor: 'pointer',
fontWeight: 'bold',
};
export default function Modal({ isOpen, onClose, children }) {
// अगर modal ओपन नहीं है, तो कुछ भी रेंडर न करें
if (!isOpen) return null;
// React Portals को 'portal-root' div में माउंट करें
const portalNode = document.getElementById('portal-root');
if (!portalNode) {
console.error("The element #portal-root was not found in the DOM.");
return null;
}
return ReactDOM.createPortal(
<div style={BACKDROP_STYLES} onClick={onClose}>
<div style={MODAL_STYLES} onClick={(e) => e.stopPropagation()}>
<div>{children}</div>
<button style={CLOSE_BUTTON_STYLES} onClick={onClose}>
Close Modal
</button>
</div>
</div>,
portalNode
);
}
Step 4: App Component में Modal का उपयोग करना
अब हमारे मुख्य App Component में हम इस Modal को कॉल करेंगे और इसकी Open/Close state को हैंडल करेंगे।
import React, { useState } from 'react';
import Modal from './Modal';
export default function App() {
const [isModalOpen, setIsModalOpen] = useState(false);
const containerStyle = {
padding: '40px',
textAlign: 'center',
fontFamily: 'sans-serif',
};
const buttonStyle = {
padding: '12px 24px',
fontSize: '16px',
backgroundColor: '#3b82f6',
color: '#fff',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
transition: 'background-color 0.2s',
};
return (
<div style={containerStyle}>
<h1>React Portals Live Demo</h1>
<p>यह बटन दबाकर देखें कि कैसे पोर्टल की मदद से मॉडल सीधे बॉडी के नीचे रेंडर होता है!</p>
<button
style={buttonStyle}
onClick={() => setIsModalOpen(true)}
>
Open Beautiful Modal
</button>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
<h2 style={{ marginTop: 0, color: '#1e293b' }}>बधाई हो! 🎉</h2>
<p style={{ color: '#64748b', lineHeight: '1.6' }}>
यह मॉडल DOM ट्री के अंदर <code>#portal-root</code> में मौजूद है, न कि <code>#root</code> में!
इस कारण इसपर पेरेंट के CSS रूल्स और लिमिटेशन्स का कोई असर नहीं पड़ेगा।
</p>
</Modal>
</div>
);
}
---
React Portals Event Bubbling: ध्यान देने योग्य खास बात!
अब एक बहुत ही महत्वपूर्ण बात जिसे जानना हर सीनियर डेवलपर के लिए आवश्यक है। इंटरव्यू में अक्सर यह सवाल पूछा जाता है: "अगर कोई Component Portal के माध्यम से DOM में कहीं दूर रेंडर हुआ है, तो क्या उसके Events पेरेंट Component तक बबल करेंगे?"
जवाब है: हाँ, बिल्कुल करेंगे!
भले ही पोर्टल द्वारा रेंडर किया गया Element फिजिकल HTML DOM में कहीं भी हो, वह React के Virtual DOM Hierarchy में उसी जगह रहता है जहाँ उसे कोड में लिखा गया है। इसलिए, जब भी कोई Event (जैसे click, keydown) पोर्टल के अंदर ट्रिगर होता है, तो वह React Component Tree के अनुसार ही बबल (Bubble) करके ऊपर जाएगा।
उदाहरण के लिए, ऊपर दिए गए कोड में अगर हमारे <App /> component के ऊपर कोई onClick लिसनर लगा होता, तो जब आप Modal के अंदर किसी चीज़ पर क्लिक करते, तो वह क्लिक इवेंट भी App के लिसनर को ट्रिगर कर देता। यदि आप इसे रोकना चाहते हैं, तो आपको चाइल्ड एलिमेंट पर e.stopPropagation() का इस्तेमाल करना पड़ेगा, जैसा कि हमने ऊपर कोड में किया है।
---
React Portals का Use करते वक्त कौन-सी Common Errors आती हैं?
जब भी डेवलपर्स नए-नए Portals का उपयोग करना शुरू करते हैं, तो वे कुछ ऐसी गलतियाँ कर बैठते हैं जिससे एप्लीकेशन क्रैश हो जाती है या अजीब बिहेवियर शो करती है। चलिए उन्हें समझकर fix error करने के तरीके सीख लेते हैं:
1. "Target container is not a DOM element" Error
यह एरर तब आती है जब React आपके स्पेसिफाइड DOM node (जैसे #portal-root) को ढूँढ नहीं पाता। ऐसा अक्सर तब होता है जब:
- आपने
index.htmlमें वह div बनाना भूल गए हैं। - आपका कोड सर्वर पर रेंडर (Next.js / SSR) हो रहा है जहाँ
documentऑब्जेक्ट उपलब्ध नहीं होता।
सोल्यूशन: सर्वर साइड रेंडरिंग के समय हमेशा चेक करें कि document मौजूद है या नहीं। आप इसके लिए useEffect या useState का इस्तेमाल कर सकते हैं, जिससे पोर्टल सिर्फ क्लाइंट-साइड पर ही रेंडर हो:
import { useEffect, useState } from 'react';
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
return () => setMounted(false);
}, []);
if (!mounted) return null;
2. Accessibility (a11y) की समस्या
चूंकि आप अपने एलिमेंट को फिजिकली स्क्रीन के किसी दूसरे कोने में फेंक रहे हैं, कीबोर्ड से नेविगेट करने वाले यूज़र्स (जैसे Tab की का इस्तेमाल करने वाले) के लिए फ़ोकस मैनेजमेंट बिगड़ सकता है।
सोल्यूशन: हमेशा ध्यान रखें कि जब Modal ओपन हो, तो फ़ोकस Modal के पहले एलिमेंट पर चला जाए, और बंद होने पर वापस उसी बटन पर आए जिसने इसे खोला था। आप इसके लिए focus\-trap\ लाइब्रेरी का इस्तेमाल भी कर सकते हैं।
---
Best Practices: प्रदर्शन और मापनीयता (Performance & Scalability)
- Cleanups का हमेशा ध्यान रखें: अगर आप डायनामिकली कोई नया DOM Node बनाकर पोर्टल अटैच कर रहे हैं, तो Component के Unmount होते समय उस Node को DOM से रिमूव ज़रूर करें ताकि मेमोरी लीक न हो।
-
Semantic HTML का पालन करें: पोर्टल के अंदर रेंडर होने वाले मॉड्यूल्स को हमेशा सही HTML टैग्स (जैसे
<dialog>,<aside>) के साथ रैप करें ताकि स्क्रीन रीडर्स उन्हें आसानी से पहचान सकें। - Styling Modular रखें: चूंकि पोर्टल्स ग्लोबल स्कोप में जाते हैं, उनके क्लास नेम्स बहुत ही स्पेसिफिक रखें ताकि ग्लोबल स्टाइलिंग क्लैश न हो। CSS Modules या Styled Components इसके लिए सबसे बेहतरीन विकल्प हैं।
---
तो दोस्तों, आज हमने क्या सीखा?
आज की इस डिटेल्ड चर्चा में हमने सीखा कि React Portals किस तरह मुश्किल से मुश्किल CSS ओवरफ़्लो और लेआउट प्रॉब्लम्स को चुटकियों में हल कर देते हैं। हमने देखा कि React Tree के अंदर लॉजिकल पैरेंटिंग बरकरार रखते हुए भी हम HTML DOM स्ट्रक्चर में अपनी मनपसंद जगह पर डेटा कैसे रेंडर कर सकते हैं। यह न सिर्फ आपके कोड को क्लीन और मेंटनेबल बनाता है, बल्कि बड़ी एप्लिकेशन्स को स्केल करने में भी बहुत मदद करता है।
अब समय आ गया है कि आप अपने पुराने प्रोजेक्ट्स को खोलें और जहाँ भी आपने जुगाड़ लगाकर CSS के ज़रिए मोडल्स संभाले थे, उन्हें React Portals के साथ रिप्लेस करें! कोडिंग करते रहिए, सीखते रहिए और कोई भी डाउट हो तो बेझिझक पूछिए!
---
Frequently Asked Questions (FAQs)
Q1: React Portals और CSS position absolute/fixed में क्या अंतर है?
CSS fixed/absolute पोजीशन सिर्फ विज़ुअल लेआउट बदलती हैं, लेकिन यदि पैरेंट एलिमेंट पर overflow: hidden\ लगा हो, तो वे एलिमेंट अभी भी कट जाते हैं। React Portals एलिमेंट को सीधे फिजिकल DOM के दूसरे नोड में भेज देते हैं जिससे इस तरह की सभी CSS लिमिटेशन्स पूरी तरह खत्म हो जाती हैं।
Q2: क्या React Portals में React Context और Redux Store का एक्सेस मिलता है?
हाँ, बिल्कुल मिलता है! भले ही पोर्टल के ज़रिए एलिमेंट DOM में अलग जगह रेंडर होते हैं, लेकिन React Component Tree में वे अपनी मूल जगह पर ही रहते हैं। इसलिए, पेरेंट प्रोवाइडर के Context, State और Props उन्हें नॉर्मल तरीके से मिलते रहते हैं।
Q3: Next.js (SSR) में React Portals का उपयोग करते समय "document is not defined" एरर क्यों आती है?
यह एरर इसलिए आती है क्योंकि Next.js कोड को पहले सर्वर पर रेंडर करता है जहाँ window\ या document\ ऑब्जेक्ट मौजूद नहीं होता। इसे सॉल्व करने के लिए आपको यह सुनिश्चित करना होगा कि पोर्टल केवल तभी रेंडर हो जब कंपोनेंट क्लाइंट-साइड पर माउंट (useEffect के ज़रिए) हो चुका हो।
Q4: क्या एक ही React App में मल्टीपल Portals का यूज़ किया जा सकता है?
हाँ, आप एक ही एप्लीकेशन में और यहाँ तक कि एक ही पेज पर जितने चाहें उतने Portals का उपयोग कर सकते हैं। आप उन्हें document.body\ या अलग-अलग custom divs में जहाँ चाहें माउंट करा सकते हैं।
Q5: क्या React Portals का इस्तेमाल परफॉर्मेंस को धीमा करता है?
बिल्कुल नहीं! React Portals रिएक्ट के कोर इंजन का ही एक हिस्सा हैं जो अत्यधिक ऑप्टिमाइज़्ड है। इनका इस्तेमाल करने से कोई अतिरिक्त ओवरहेड नहीं होता, बल्कि यह आपके UI रेंडरिंग और CSS पेंटिंग परफॉर्मेंस को बेहतर ही बनाता है।
---