如何解决ReactDOM.createPortal() 在 next.js-typescript 中创建额外的空白 div
这是background.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;
这是 Backdoor.tsx 的 css
.backdrop {
width: 100%;
height: 100vh;
background: rgba(0,0.75);
z-index: 100;
position: fixed;
left: 0;
top: 0;
transition: opacity 0.3s ease-out;
opacity: 1;
}
解决方法
您的代码将在每次 div.backdrop
重新渲染时创建 Backdrop
。正确的方法应该是创建一次。正确的方法是使用 useEffect
来保证 ReactDOM.createPortal
只执行一次。并应用 useRef
以确保 container
在每次渲染中保持相同的实例。
const containerRef = useRef<HTMLDivElement>(null);
useEffect({
// Will be execute once in client-side
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
containerRef.current = rootContainer;
}
},[window])
useEffect({
// Will be execute once when containerRef is bind to <HTMLDivElement>
if(containerRef.current) {
ReactDOM.createPortal(
<div
className={["backdrop",props.open ? "open" : ""].join(" ")}
onClick={props.onClick}
/>,containerRef.current
)
}
},[containerRef])
编辑
-
我删除了
window
中的存在检测,因为useEffect
只会在客户端执行。 -
由于
ReactDOM.createPortal
将在根div.backdrop
(HTMLElement
) 之外创建div#next
,我认为只需在 {{1} 中返回null
}} 组件很好。
Backdrop
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。