这是我的react app组件结构
<App>
<Body>
<Top>
### //<- Position 1
</Top>
<Middle>
<MyComponent/>
</Middle>
</Body>
</App>
我希望<MyComponent/>
随时在Position 1
处呈现。
我已经尝试过ReactDom.createPortal
,但一直得到Target container is not a DOM element
。如果这不可能,那么我如何才能最好地完成类似的设置。
我尝试过的
//Top.js
<Top>
<div id="top-render"/>
</Top>
//MyCustomElement.js
class MyCustomElement extends Component{
render(){
return (<div>Demo Text</div>)
}
}
export default props => ReactDOM.createPortal(
<MyCustomElement />,
document.getElementById('top-render'),
);
//Middle.js
<Middle><MyCustomElement/></Middle>
答案 0 :(得分:4)
您将收到Target container is not a DOM element
错误,因为在执行到达您的ReactDOM.createPortal()
调用时,document.getElementById('top-render')
试图检索的DOM节点尚未写入到DOM。
这是因为到那时,React还没有成功通过组件树。也就是说,React尚未成功创建组件树中所有内容的虚拟表示,因此尚未向DOM写入任何内容。因此,尽管您期望top-render
div在DOM中存在,但实际上尚未编写。
解决方案是创建一个<MyComponent
拥有的DOM节点,其中将包含它的子节点(我们称此节点el
),然后将该DOM节点作为目标{ {1}}调用(又是第二个参数)。然后,在挂载React.createPortal()
时,您只需检索<MyComponent>
div并将top-render
附加到它。像这样:
el
我整理了一个working example。
这种方法行之有效,因为React保证const MyCustomComponent = () => {
return (<div>Demo Text: from "MyCustomComponent"</div>)
}
class MyComponent extends React.Component {
el = document.createElement("div");
componentDidMount() {
// saving this on the component so we can access it in `componentWillUnmount` later
this.targetEl = document.getElementById("top-render");
this.targetEl.appendChild(this.el);
}
componentWillUnmount() {
this.targetEl.removeChild(this.el);
}
render() {
return ReactDOM.createPortal(<MyCustomComponent />, this.el);
}
}
将在组件安装后立即被调用(也称为写入DOM)。换句话说,我们可以肯定地知道,到componentDidMount()
被调用时,我们的组件树至少已被写入DOM一次,因此componentDidMount()
div已存在于DOM中。>
答案 1 :(得分:0)
“随时导入”是什么意思?
无论如何,您只能使用条件渲染。它将完成工作,但看来您的意图还不是其他!
render(){
const { showMyComp } = this.state
return(
<App>
<Body>
<Top>
{showMyComp && (<MyComponent />)}
</Top>
<Middle>
<MyComponent/>
</Middle>
</Body>
</App>
)
}
答案 2 :(得分:0)
ReactDom.createPortal
节点上使用 DOM
。在内部,您通常应<Top><MyComponent/></Top>
声明一个组件。
但是出于好奇,如果只想使用这种方法,则应在Top
元素中使用DOM节点的引用。
ReactDOM.createPortal(
<MyComponent/>,
/*Ref of Container element*/,
);