reactjs - 使用 useEffect 时反应 createPortal 未触发
问题描述
我有模态组件,但它根本没有呈现。我试图找出问题,但我似乎无法找到答案。
这是我的代码:
export default React.memo(function DialogComponent({
children,
className,
closeModal,
extraOptionClassName,
title,
visible,
...attributes
}: Props) {
let modalRoot: HTMLElement;
modalRoot = document.getElementById('MainGrid_row1');
if (!modalRoot) {
modalRoot = document.getElementById('MainGrid');
}
if (modalRoot == null) {
modalRoot = document.createElement('div');
console.log(modalRoot);
}
const el: HTMLElement = document.createElement('div');
el.classList.add('c-dialog');
useEffect(() => {
if (el && modalRoot) {
modalRoot.appendChild(el);
}
return () => {
if (el && modalRoot && modalRoot.contains(el)) {
modalRoot.removeChild(el);
}
};
}, [el]);
return createPortal(
<div
{...attributes}
className={cx(
'c-dialog',
{
'c-dialog': visible,
'c-dialog--hidden': !visible,
},
className,
`c-dialog--${extraOptionClassName}`
)}
>
<div
className={`c-dialog__modal-window c-dialog__modal-window${
!visible ? '--hidden' : '--visible'
}`}
onClick={() => closeModal()}
>
<div
className="c-dialog__window"
onClick={e => {
e.stopPropagation();
}}
>
<div className="c-dialog__top-wrapper">
<div className="c-dialog__close">
<div className="c-dialog__x-logo" onClick={() => closeModal()}>
{crossIconSelect}
</div>
</div>
</div>
<Item>{children}</Item>
</div>
</div>
</div>,
el
);
});
return createPortal 未触发或返回。这里可能是什么问题?我可以看到 useEffect 工作正常。我正在使用故事书 UI 组件资源管理器
谢谢您的帮助
沙箱:https ://codesandbox.io/s/cranky-gagarin-fhsoc?file=/src/App.tsx
解决方案
主要问题是您忘记将新创建的 Div 插入正文中;所以它只是在记忆中。
同样在每次组件重新渲染时,它都会在代码中重新创建el
元素;我不认为你想要什么。
export default React.memo(function DialogComponent({
children,
className,
closeModal,
extraOptionClassName,
title,
visible,
...attributes
}: Props) {
// no need for all that boilerplate code.
const modalRoot = document.getElementById('MainGrid_row1') || document.getElementById('MainGrid');
useEffect(() => {
// YOU NEED TO INSERT THIS DIV SOMEWHERE
// newly createdElement is just in memory in your code. add it to body for example
// remember its immutable; you can append el to it later it will work;
if (!modalRoot) {
modalRoot = document.createElement('div');
document.body.append(modalRoot);
console.log(modalRoot);
}
// el will change on ever render if outside. move it inside useEffect
const el: HTMLElement = document.createElement('div');
el.classList.add('c-dialog');
modalRoot.appendChild(el);
return () => {
document.removeChild(modalRoot);
};
}, []);
return createPortal( ... rest of your code ... )
推荐阅读
- laravel - 如何在 Laravel 7 中进行身份验证时重定向到动态子域
- rust - 为什么 Rust 需要此变量的“静态”生命周期?
- django - 停止 Redis 后如何继续执行 celery 队列,然后再启动它?
- reactjs - 在受控的 REACT 组件中处理表单输入状态的最佳方法是什么?
- python - 在第一次迭代时跳过循环?
- django - ValueError:字段“id”需要一个数字,但得到“耳语”
- github - 当 Windows 与 ssh 密码一起启动时启动 ssh-agent
- ionic-framework - Ionic Appflow 和 GitHub 连接列表不完整,并且缺少 Repo 条目
- java - 更新 Intellij 后连接 MongoDB 时出错:java.lang.NoSuchMethodError:org.bson.io.BasicOutputBuffer。
(一)五 - c# - ASP Core 3.1 多个/备用数据库上下文