You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

技术问询:能否在<React.Fragment>内使用ReactDOM.createPortal?

当然可以!完全没问题

你完全可以在<React.Fragment>(或者它的简写形式<>...</>)里同时放置普通元素和通过ReactDOM.createPortal渲染的内容——这不仅是允许的,还是React里很常见的用法,比如处理模态框、全局通知这类需要脱离当前DOM流但逻辑上属于组件一部分的场景。

为什么可行?

<React.Fragment>的核心作用就是包裹多个React元素,同时不在真实DOM中生成额外的父节点,它对包裹的内容类型没有限制。而createPortal的本质是:把组件的内容渲染到DOM树的另一个位置,但在React的虚拟DOM结构里,它依然是当前组件的子节点,和Fragment里的其他普通元素属于同级的兄弟关系,不会产生冲突。

举个实际的例子

假设你有一个组件,既要在当前位置展示内容,又要通过Portal渲染一个模态框:

import React from 'react';
import ReactDOM from 'react-dom';

function CombinedComponent() {
  // 提前在HTML里准备好挂载Portal的容器,比如<div id="modal-root"></div>
  const modalContainer = document.getElementById('modal-root');

  return (
    <> {/* 这里用简写的Fragment */}
      {/* 这个div会渲染到组件所在的原始DOM位置 */}
      <div className="card">
        <h3>我是组件本地的内容</h3>
        <p>点击按钮打开模态框</p>
      </div>
      {/* 这个Portal内容会渲染到#modal-root容器里 */}
      {ReactDOM.createPortal(
        <div className="modal-overlay">
          <div className="modal">
            <h2>我是Portal渲染的模态框</h2>
            <button>关闭</button>
          </div>
        </div>,
        modalContainer
      )}
    </>
  );
}

可能的操作误区(你可以自查一下)

如果你的代码没达到预期,可能是这些小问题:

  • 忘记在HTML中提前创建Portal要挂载的目标DOM节点,导致Portal找不到挂载位置而无法渲染
  • 没有用Fragment(或者其他合法的父容器)包裹多个元素,导致React报错“Adjacent JSX elements must be wrapped in an enclosing tag”
  • 误解了Portal的事件冒泡逻辑:虽然Portal渲染在其他DOM位置,但事件依然会按照React的组件树向上冒泡,这是正常特性,不是bug

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

火山引擎 最新活动