this is backdrop.tsx:
interface BacdropProps {
open?: string;
onClick: () => void;
}
const Backdrop: React.FC<BacdropProps> = (props) => {
let container: HTMLDivElement | null = null;
if (typeof window !== "undefined") {
const rootContainer = document.createElement("div");
const parentElem = document.querySelector("#__next");
parentElem?.insertAdjacentElement("afterend", rootContainer);
// parentElem?.after(rootContainer) this gives me same issue
container = rootContainer;
}
return container
? ReactDOM.createPortal(
<div
className={["backdrop", props.open ? "open" : ""].join(" ")}
onClick={props.onClick}
/>,
container
)
: null;
};
export default Backdrop;
this is css for Backdoor.tsx
.backdrop {
width: 100%;
height: 100vh;
background: rgba(0, 0, 0, 0.75);
z-index: 100;
position: fixed;
left: 0;
top: 0;
transition: opacity 0.3s ease-out;
opacity: 1;
}
Your code will create
div.backdrop
every time whenBackdrop
re-render. The correct way should be create it once. The correct way is usinguseEffect
to promiseReactDOM.createPortal
just be executed once. And also apply theuseRef
to make surecontainer
to keep the same instance in every render.Edit
I removed the detection of existence in
window
, sinceuseEffect
would be executed only in client-side.Since
ReactDOM.createPortal
will create thediv.backdrop
outside of the rootHTMLElement
(div#next
), i think just returnnull
inBackdrop
component is fine.