Portals से Modals बनाना (व्यावहारिक उपयोग)
In this page:
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 के आधार पर दिखता और गायब होता।
उदाहरण: Building a Basic Portal-Based Modal
<!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 होने पर हटाता है।
उदाहरण: Closing with the Escape Key
<!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 कर देता है।
उदाहरण: Preventing Background Scroll While Open
<!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>
- Modal बंद करने के लिए Escape key या backdrop click handle न करना, जो user को इसके अंदर trap कर देता है।
- Modal open रहने के दौरान body scroll रोकना भूल जाना, जो page को इसके पीछे awkwardly scroll करने देता है।
- 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 हुआ)।
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first:
- Error Boundaries
- React Portals
- Modals using Portals (practical use)
- React Suspense
- Code Splitting with React.lazy
- Introduction to Server Components
- Introduction to Next.js (server-side React)
- Using React with TypeScript
- Scalable Folder Architecture
- Common React Design Patterns
- Component Documentation with Storybook
- Accessibility (a11y) in React
- i18n with react-i18next
- React Security Best Practices