使用React Portal将孩子渲染到父组件的DOM节点中

时间:2019-03-15 19:16:19

标签: javascript reactjs dom

我正在尝试做的事情似乎有些不合常规,请耐心等待。

我想使用React Portal将子组件渲染到父组件的DOM节点中。

您可能会想:“这不是门户网站的目的,您应该只在需要的位置呈现孩子。”

您可能是对的,但这是我尝试了许多其他方式后尝试使用的实验方法的简化示例。

无论如何,这是代码:(sandbox here)

const Child = ({ color }) => {
  let jsx = <h1>Wow! I am {color}!</h1>;
  let node = document.getElementById(color);
  return ReactDOM.createPortal(jsx, node);
};

class Parent extends React.Component {
  state = {
    color: "green"
  };
  changeColor = () => {
    let color = this.state.color === "green" ? "blue" : "green";
    this.setState({ color });
  };
  render() {
    return (
      <div className="App">
        <Child color={this.state.color} />
        <button onClick={this.changeColor}>change color</button>
        <div className="green" id="green">
          I render green stuff:
        </div>
        <div className="blue" id="blue">
          I render blue stuff:
        </div>
      </div>
    );
  };
};

问题在于,当Child尝试向其中渲染一些jsx时,尚未渲染Parent组件的“ blue”和“ green” div。所以我得到了错误Target container is not a DOM element。我使它起作用的唯一方法是将这些div放在根目录下的html文件中。

关于如何使用门户网站尝试做的任何建议?请不要仅仅这样做:

<div className="App">
  <button onClick={this.changeColor}>change color</button>
  <div className="green" id="green">
    I render green stuff:
    {this.state.color === 'green' && <Child color='green' />}
  </div>
  <div className="blue" id="blue">
    I render blue stuff:
    {this.state.color === 'blue' && <Child color='blue' />}
  </div>
</div>

预先感谢您:-)

1 个答案:

答案 0 :(得分:1)

是的,所以您的问题是,(此时)您不能(通过它们的ID)查找div,因为它们是由父组件渲染的,并且它们不在您想像的DOM中。 / p>

但是!您可以使用裁判来节省一天!这是一个示例:https://codesandbox.io/s/r78mplox64?fontsize=14

我替换了功能组件的类,因为这些钩子可以使它更清晰。基本上,它所做的全部工作就是将两个ref传递给color div,并且在渲染之后,ref的当前值将指向该节点。挂载的useEffectcolorNode的状态设置为蓝色ref(即<div id="blue">节点)的当前值。

然后,单击按钮仅交换出color变量和color节点。然后,两者都作为prop传递,而colorNode prop作为门户呈现的节点传递。