我有index.html
<body>
<div id="portal"></div>
<div id="root"></div>
</body>
,并希望在portal div
之外的root div
中使用以下组件,
import React from 'react';
const portalDiv = document.getElementById('portal');
function Portal1(props) {
return ReactDOM.createPortal(
<div>
{props.children}
<div/>,
portalDiv); //here
}
export default Portal1;
但是我遇到此错误,类型'HTMLElement |的参数。 “ null”不可分配给“ Element”类型的参数。 VScode中的类型'null'不能分配给类型'Element'.ts(2345)。
我正在使用Typescript。请帮忙。
答案 0 :(得分:6)
其他人已经回答您应该添加一个null检查,但是Typescript还具有一个非null断言,当您确定通过添加{ {1}}运算符,直到语句结尾:
!
答案 1 :(得分:5)
所以我不知道是否有人仍然遇到这个问题,但有一个更简单直接的解决方案。
只需使用 "as" 关键字声明模态元素
const modalRoot = document.getElementById("modal-root") as HTMLElement;
这消除了错误。
我建议查看这个很棒的 react-typescript 备忘单。
https://github.com/typescript-cheatsheets/react
答案 2 :(得分:2)
getElementById
可以返回null
,但是createPortal
不接受null
。
如果 知道 该门户网站div将存在,则使代码明确相关:
const portalDiv = document.getElementById('portal');
if (!portalDiv) {
throw new Error("The element #portal wasn't found");
}
这将使TypeScript缩小常量的类型,而删除该类型的| null
部分。如果有人更改了某些内容,例如当该代码再次运行时div不存在,它还会给您一个很好的主动警告。
答案 3 :(得分:1)
由于getElementById
可能返回null。因此,您只需在使用like之前先检查一下即可:
function Portal1({ children }) {
return portalDiv ? ReactDOM.createPortal(<>{children}</>, portalDiv) : null;
}
答案 4 :(得分:1)
我认为最好的解决方案不是使其成为 null 或 HTMLDIVElement 而是在用例 尝试让 typescript 知道 DivElement 此刻可能是空的,但你会只需使用“!”就可以承担责任符号。
以下代码示例:
import React, {useEffect} from 'react';
import ReactDOM from 'react-dom';
import './modal-portlet.style.scss';
const modalRoot = document.getElementById('modalRoot');
type Props = {
children: JSX.Element;
};
const ModalPortlet: React.FC<Props> = ({children}): JSX.Element => {
const divContainer = window.document.createElement('div');
divContainer.setAttribute('class', 'modal-container');
useEffect(() => {
/**********
* immediately the component mount append @divContainer as the childNode of @modalRoot in the DOM
**********/
modalRoot!.appendChild(divContainer);
return () => {
modalRoot!.removeChild(divContainer);
};
});
/************
* return the createPortal api that takes the children(JSX) and inject it into @divContainer which is already a childNode of @modalRoot
************/
return <>{ReactDOM.createPortal(children, divContainer)}</>;
};
export default ModalPortlet;