← Back to React Course | Chapter 13: Advanced React & Architecture | Lesson 3 of 14

Portals से Modals बनाना (व्यावहारिक उपयोग)

Portal से बना एक modal एक असली physical drawer खोलने जैसा है जो आपके desk पर हर चीज़ के ऊपर बैठता है, बजाय इसके कि आप एक note को एक already full folder में squeeze करने की कोशिश करें।
Syntax
markup
function Modal({ isOpen, onClose, children }) {
  if (!isOpen) return null;
  return createPortal(
    <div className="overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}

एक Basic Portal-Based Modal बनाना

createPortal को conditional rendering के साथ combine करना (portal के content को तभी render करना जब isOpen true हो) आपको एक working modal देता है: एक backdrop plus एक content box, document.body में render हुआ, एक simple boolean state के आधार पर दिखता और गायब होता।

Note: जब isOpen false हो तो null render करें, हमेशा render करके CSS से hide करने के बजाय, ताकि modal बंद होने पर DOM clean रहे।
Warning: बिना किसी backdrop element के (even just एक semi-transparent overlay), modal ऐसा लग सकता है जैसे यह बाकी UI से disconnected floating कर रहा हो।

उदाहरण: Building a Basic Portal-Based Modal

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function Modal({ isOpen, onClose, children }) {
  if (!isOpen) return null;
  return ReactDOM.createPortal(
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.5)" }} onClick={onClose}>
      <div style={{ background: "white", padding: "16px", margin: "50px auto", width: "200px" }} onClick={e => e.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}
function App() {
  const [isOpen, setIsOpen] = React.useState(false);
  return (
    <div>
      <button onClick={() => setIsOpen(true)}>Open Modal</button>
      <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}><p>Modal content</p></Modal>
    </div>
  );
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>

Escape Key से बंद करना

एक well-behaved modal को तब भी बंद होना चाहिए जब user Escape press करे, सिर्फ backdrop click करने पर नहीं। एक useEffect के अंदर एक keydown event listener जोड़ना (सिर्फ modal open रहने के दौरान) यह implement करता है, cleanup के साथ जो listener को modal बंद होने या unmount होने पर हटाता है।

Note: Keydown listener को सिर्फ तब add करें जब isOpen true हो, और effect के dependency array में isOpen शामिल करें ताकि इसे सही तरीके से add/remove किया जाए।
Warning: Cleanup में इस listener को remove करना भूल जाने का मतलब है कि यह modal बंद होने के बाद भी active रहता है, potentially Escape presses को respond करते हुए जब इसे नहीं करना चाहिए।

उदाहरण: Closing with the Escape Key

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function Modal({ isOpen, onClose, children }) {
  React.useEffect(() => {
    if (!isOpen) return;
    const handleKey = e => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", handleKey);
    return () => window.removeEventListener("keydown", handleKey);
  }, [isOpen, onClose]);
  if (!isOpen) return null;
  return ReactDOM.createPortal(
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.5)" }}>
      <div style={{ background: "white", padding: "16px", margin: "50px auto", width: "220px" }}>
        {children}<p style={{fontSize: "12px"}}>(Press Escape to close)</p>
      </div>
    </div>,
    document.body
  );
}
function App() {
  const [isOpen, setIsOpen] = React.useState(true);
  return <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}><p>Try pressing Escape</p></Modal>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>

Open रहते हुए Background Scroll रोकना

जब तक एक modal open है, उसके पीछे page का scroll होना disorienting feel कर सकता है। Modal open रहने के दौरान document.body.style.overflow को hidden set करना, और इसे effect के cleanup में restore करना, उस duration के लिए background scrolling lock कर देता है।

Note: Cleanup में हमेशा original overflow value restore करें (या बस style हटा दें), ताकि modal बंद करने से scrolling permanently lock न हो।
Warning: Cleanup में overflow style restore करना भूल जाने से पूरा page modal बंद होने के बाद भी scroll करने में असमर्थ रह जाता है।

उदाहरण: Preventing Background Scroll While Open

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function Modal({ isOpen, children }) {
  React.useEffect(() => {
    if (isOpen) document.body.style.overflow = "hidden";
    return () => { document.body.style.overflow = ""; };
  }, [isOpen]);
  if (!isOpen) return null;
  return ReactDOM.createPortal(
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.5)" }}>
      <div style={{ background: "white", padding: "16px", margin: "50px auto", width: "220px" }}>{children}</div>
    </div>,
    document.body
  );
}
function App() {
  return <Modal isOpen={true}><p>Background scroll is locked while I'm open</p></Modal>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. Modal बंद करने के लिए Escape key या backdrop click handle न करना, जो user को इसके अंदर trap कर देता है।
  2. Modal open रहने के दौरान body scroll रोकना भूल जाना, जो page को इसके पीछे awkwardly scroll करने देता है।
  3. Focus manage न करना — एक truly accessible modal को open रहते हुए keyboard focus इसके अंदर trap करना चाहिए।
चैप्टर सारांश
  • एक modal React Portals का एक natural, practical use case है, क्योंकि इसे visually हर चीज़ के ऊपर बैठने की ज़रूरत है।
  • एक real modal implementation को एक backdrop, एक close mechanism (button, Escape key, backdrop click), और ideally focus management भी चाहिए।
  • Portal को conditionally render करना (सिर्फ तब जब isOpen true हो) हमेशा render करने और CSS से visibility toggle करने से simpler है।
  • createPortal उपयोग करना modal के JSX को उस component के साथ colocated रखता है जो इसे खोलता है, जबकि इसका DOM page के top पर रहता है।
ब्राउज़र सपोर्ट

React 16.0 से available (Portals introduce हुआ)।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.