Portaler til modaler og tooltips
Brug ReactDOM.createPortal til at rendere underkomponenter i en anden DOM-node, så modaler og tooltips kan undslippe containere med overflow:hidden.
Portaler til modaler og tooltips er en gratis Frontend Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Frontend Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Frontend Academy-kurset indeholder 4 lektioner i alt.
Problemet med at undslippe containere
Modale vinduer og værktøjstip skal gengives øverst i DOM'en, så de undslipper forælderens overflow:hidden, z-index-stabling og transform-baserede kontekster. Løsningen er portaler.
createPortal-API'en
createPortal(children, container) gengiver children i container, altså en vilkårlig DOM-node, samtidig med at de logisk forbliver underkomponenter af React-komponenten med hensyn til hændelser og kontekst.
import { createPortal } from 'react-dom';
function Modal({ children, onClose }) {
return createPortal(
<div className="modal-backdrop" onClick={onClose}>
<div className="modal-content" onClick={e => e.stopPropagation()}>
{children}
</div>
</div>,
document.body
);
}Portalcontainere
Almindelige mål er document.body, en dedikeret #modal-root-div i index.html eller en container via ref, som oprettes efter behov.
<!-- index.html -->
<div id="root"></div>
<div id="modal-root"></div>
// component:
const modalRoot = document.getElementById('modal-root');
return createPortal(<div>...</div>, modalRoot);Hvorfor ikke bare gengive direkte?
Hvis en forælder har overflow: hidden, bliver et underliggende modalt vindue beskåret. Hvis en forælder har transform: scale, bliver modalvinduets faste positionering relativ til forælderen. Portaler undgår alt dette.
Hændelser bobler stadig op
Selvom indholdet gengives et andet sted i DOM'en, bobler React-hændelser gennem komponenttræet og ikke DOM-træet. Et klik i portalen bobler stadig op til onClick-håndteringer på overordnede React-komponenter.
Lukning ved klik på overlayet
Stop hændelsespropageringen på modalindholdet, så klik inden i det ikke lukker modalvinduet.
function Modal({ onClose, children }) {
return createPortal(
<div className="backdrop" onClick={onClose}>
<div className="content" onClick={e => e.stopPropagation()}>
{children}
</div>
</div>,
document.body
);
}Lukning med Escape-tasten
Tilføj en keydown-lytter, mens modalvinduet er åbent, og fjern den, når komponenten afmonteres.
useEffect(() => {
const onKey = (e) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, [onClose]);Fokusstyring i portaler
Når et modalt vindue åbnes: flyt fokus ind i det, fasthold fokus, indtil det lukkes, og gendan derefter fokus på det element, der åbnede modalvinduet. Brug et bibliotek som focus-trap-react for at undgå at implementere dette igen.
Det indbyggede dialog-element
HTML's <dialog> håndterer modal positionering, baggrund, fokusfastholdelse og lukning med Escape indbygget. Til de fleste modale vinduer er det et bedre udgangspunkt end en portal.
function Modal({ open, onClose, children }) {
const ref = useRef(null);
useEffect(() => {
if (open) ref.current?.showModal();
else ref.current?.close();
}, [open]);
return (
<dialog ref={ref} onClose={onClose}>
{children}
</dialog>
);
}Værktøjstip og popovers
Værktøjstip positioneres relativt til et ankerelement. En portal lader dem undslippe stablingskontekster. Kombinér med floating-ui til kollisionsregistrering, vending og positionering.
import { useFloating, autoUpdate } from '@floating-ui/react';
function Tooltip({ children, content }) {
const { refs, floatingStyles } = useFloating({ whileElementsMounted: autoUpdate });
const [open, setOpen] = useState(false);
return (
<>
<button ref={refs.setReference} onMouseEnter={() => setOpen(true)} onMouseLeave={() => setOpen(false)}>
{children}
</button>
{open && createPortal(
<div ref={refs.setFloating} style={floatingStyles}>{content}</div>,
document.body
)}
</>
);
}SSR-forbehold
document findes ikke på serveren. Gengiv enten kun på klienten, ved at kontrollere typeof window, eller brug Next.js' dynamic med ssr:false.
Tilgængelighed: aria-modal
Modale containere bør have role="dialog", aria-modal="true" og aria-labelledby, der peger på modalvinduets overskrift. Eller brug det indbyggede <dialog>-element.
Hurtigt tjek
Hvorfor skal du bruge createPortal til modale vinduer i stedet for at gengive dem direkte i komponenttræet?
Opsummering: Portaler
createPortal(children, container) gengiver DOM-indhold et andet sted, samtidig med at det logiske React-træ bevares. Det løser problemer med at undslippe overflow, transform og z-index. Hændelser bobler stadig gennem React-træet. Tilføj lukning med Escape og fokusstyring. Det indbyggede <dialog>-element håndterer meget af dette for modale vinduer. Kombinér med floating-ui til værktøjstip. Glem ikke SSR, og kontrollér typeof window.
Lær HTML med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 41
- Lektioner
- 163
Ofte stillede spørgsmål
Er lektionen “Portaler til modaler og tooltips” gratis?
Ja — hele teksten til “Portaler til modaler og tooltips” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Frontend Academy-kurset, skal du opgradere til CoddyKit PRO. Frontend Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Portaler til modaler og tooltips”?
Brug ReactDOM.createPortal til at rendere underkomponenter i en anden DOM-node, så modaler og tooltips kan undslippe containere med overflow:hidden. Du øver dig i Frontend Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Frontend Academy?
Der kræves ingen tidligere erfaring. Frontend Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Portaler til modaler og tooltips”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Frontend Academy-lektion?
Ja. Alle Frontend Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Sammensatte komponenter med Context
- Render Props- og HOC-mønstre
- Portaler til modaler og tooltips
- Error Boundaries