Make the Page Portal-Proof
Optimization

Make the Page Portal-Proof

When your page is embedded, things are a bit different.

Rene Wang·
Content below is from this post.

A theme provider with a keyboard shortcut—Cmd+D to toggle dark mode:

function ThemeProvider({ children }) {
	const [theme, setTheme] = useState("light");
 
	useEffect(() => {
		const toggle = (e) => {
			if (e.metaKey && e.key === "d") {
				e.preventDefault();
				setTheme((t) => (t === "dark" ? "light" : "dark"));
			}
		};
		window.addEventListener("keydown", toggle);
		return () => window.removeEventListener("keydown", toggle);
	}, []);
 
	return <div className={theme}>{children}</div>;
}

But if someone renders the app inside a pop-out window, iframe, or via createPortal, the shortcut stops working. The listener is attached to the parent window, not the one your component lives in. Use ownerDocument.defaultView:

function ThemeProvider({ children }) {
	const [theme, setTheme] = useState("light");
	const ref = useRef(null);
 
	useEffect(() => {
		const win = ref.current?.ownerDocument.defaultView || window;
		const toggle = (e) => {
			if (e.metaKey && e.key === "d") {
				e.preventDefault();
				setTheme((t) => (t === "dark" ? "light" : "dark"));
			}
		};
		win.addEventListener("keydown", toggle);
		return () => win.removeEventListener("keydown", toggle);
	}, []);
 
	return (
		<div ref={ref} className={theme}>
			{children}
		</div>
	);
}

Now the shortcut works in any window context.

More Details