弹出框类型的组件通常是在 body 内渲染的。用 react 实现这类组件时就需要在组件 mount 之后再把 dom 移到 body 里。
如果我们直接把整个 component 的 dom 放到 body 里,而我们又在使用 react router 之类的会切换内容的功能。那么很有可能我们会在内容切换时得到错误:Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
。因为 react 认为我们的 component 没有移动过位置,它用我们的 component 作为参照,尝试往 component 之前添加 dom 。
解决方法很简单:给我们的 component 多套一层。在我们想要移动 dom 时,只移动内容,保留外层,
let Popup = React.createClass({
componentDidMount() {
let { container, content } = this.refs;
// Move entire component into body.
// React might throw error when it tries to inject dom before our component.
document.body.appendChild(container);
// Move content into body, leave container there. Safe way to do it.
document.body.appendChild(content);
},
render() {
return (
<div ref="container">
<div ref="content"></div>
</div>
);
}
});