You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用React Portal?React v16.2中Portal功能失效求助

解决React Portal不显示的问题(React v16.2)

嘿,我明白你遇到的问题了——React Portal的使用方式有点小误区,咱们一步步来修正它!

先理清楚你当前的代码情况:

你的原始代码

HTML部分:

<div id="app-root"></div>
<div id="toast-root"></div>

JavaScript部分(还原后):

const appRoot = document.getElementById('app-root');
const toastRoot = document.getElementById('toast-root');

const insertToast = (toastRoot) => ReactDOM.createPortal(
  'yey!',
  toastRoot,
);

class App extends React.Component {
  insertToasts() {
    // 这里你应该是调用了insertToast,但没正确处理渲染逻辑
    insertToast(toastRoot);
  }

  render() {
    return (
      <div>
        <a onClick={() => this.insertToasts()}>click me</a>
      </div>
    );
  }
}

ReactDOM.render(<App />, appRoot);

问题核心

ReactDOM.createPortal()返回的是一个React元素,但你只是调用了这个函数,并没有把这个元素纳入React的渲染流程。Portal本质还是React元素,必须作为组件render输出的一部分,或者通过ReactDOM.render主动挂载,才能被React识别并渲染到目标容器。

修正方案(推荐:状态驱动渲染)

用组件状态控制Portal的显示/隐藏,把Portal作为render方法的一部分返回,完全贴合React的组件化思想:

const appRoot = document.getElementById('app-root');
const toastRoot = document.getElementById('toast-root');

class App extends React.Component {
  // 用状态控制toast的显示状态
  state = {
    showToast: false
  };

  toggleToast = () => {
    this.setState(prevState => ({ showToast: !prevState.showToast }));
  };

  render() {
    return (
      <div>
        <a onClick={this.toggleToast}>click me</a>
        {/* 根据状态决定是否渲染Portal */}
        {this.state.showToast && ReactDOM.createPortal(
          'yey!',
          toastRoot
        )}
      </div>
    );
  }
}

ReactDOM.render(<App />, appRoot);

为什么这样能行?

  1. 状态驱动更新:点击链接时切换showToast状态,React会自动触发组件重新渲染,包括Portal部分。
  2. Portal纳入渲染树:把Portal放在组件的render输出里,React能追踪它的生命周期,确保正确渲染到目标容器toast-root中。

备选方案:动态挂载Portal

如果需要在事件里直接创建Portal(不依赖组件状态),可以用ReactDOM.render主动挂载:

const appRoot = document.getElementById('app-root');
const toastRoot = document.getElementById('toast-root');

class App extends React.Component {
  insertToasts = () => {
    // 直接把Portal渲染到目标容器
    ReactDOM.render(
      ReactDOM.createPortal('yey!', toastRoot),
      toastRoot
    );
  };

  render() {
    return (
      <div>
        <a onClick={this.insertToasts}>click me</a>
      </div>
    );
  }
}

ReactDOM.render(<App />, appRoot);

不过这种方式需要自己管理Portal的卸载(比如调用ReactDOM.unmountComponentAtNode(toastRoot)),不如状态驱动的方式省心。

内容的提问来源于stack exchange,提问作者JoeTidee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:09:51