June 11, 2026
Portal-proof components
Social apps love pop-out windows. A direct message thread you tear off into its own window, a composer that opens in a separate browser window so people can keep scrolling. The moment your component renders into a portal or a pop-out, the global window stops being the window it actually lives in.
The wrong window
Here is a keyboard shortcut that opens the composer when the user presses the letter n.
function ComposerShortcut({ onOpen }) {
useEffect(() => {
const handler = (e) => {
if (e.key === 'n') onOpen()
}
window.addEventListener('keydown', handler)
return () => window.removeEventListener('keydown', handler)
}, [onOpen])
return null
}
If this component renders inside a pop-out chat window, it still listens on the main window. Pressing n in the pop-out does nothing, because the listener is attached to the wrong document entirely.
The fix
Reach for the document the component is actually mounted in, through ownerDocument.defaultView. Fall back to window for the normal case.
function ComposerShortcut({ onOpen }) {
const ref = useRef(null)
useEffect(() => {
const win = ref.current?.ownerDocument.defaultView || window
const handler = (e) => {
if (e.key === 'n') onOpen()
}
win.addEventListener('keydown', handler)
return () => win.removeEventListener('keydown', handler)
}, [onOpen])
return <span ref={ref} hidden />
}
Now the shortcut binds to whichever window the component truly lives in, portal or not.