antd Modal内部组件的渲染时机?

一个自定义 Modal 组件,为什么这里子组件的 getLogTable 函数会在子组件渲染的时候执行啊?
不应该等到 showOperationLogModaltrue 的时候才渲染 Modal 内部的内容吗?

父组件(初始值为false)

<OperateLogModal showOperationLogModal={showOperationLogModal} />

子组件

const OperateLogModal = (props) => {
  const { showOperationLogModal } = props;

  return (
    <div>
      <Modal
        className="w-modal"
        title="版本日志"
        visible={showOperationLogModal}
        maskClosable
        destroyOnClose
        onCancel={onCancelLog}
        footer={null}
      >
        {getLogTable()}
      </Modal>
    </div>
  );
};

这里和函数加括号立即执行应该没关系吧。可能还是在于 Modal 在渲染时机,有佬讲解下吗,应该是什么问题呢

阅读 1.4k
4 个回答

看那么久了还没人回答,但是我不怎么用React,所以我就按照我对于JS运行机制的理解回答一下。

你的 showOperationLogModal 但是你的内容物 { getLogTable() } 还是需要被执行的,然后返回结果传递给 Modal 的内容插槽当中。只不过最终处理完的 Modal 组件并不会被渲染到页面当中。

如果你有一些执行条件,可以做一些条件判断,比如说:{ showOperationLogModal ? getLogTable() : '' },来保证 getLogTable 不会被执行。

当然可能这个处理会不合理,那就需要React技术栈的开发者来回答了。

你说个的这个现象到很有意思。
antdModal第一次没有打开时,Modal和它的子组件都是不会渲染的,但是当你打开过1次之后,即使关闭Modal,子组件其实还在DOM中,当然要确保destroyOnClose的值是false;
如果destroyOnClosetrue,那关闭的时候就会销毁;这个你可以打开F12来测试查看DOM的情况;
如果说你真的遇见上述说的情况,我猜测有没有一种可能 showOperationLogModal 其实也变成true了,然后又变成false,具体得看下你的业务代码,或者你可以单独写一个组件只测试 Modal

当调用 ReactDOM.render(或通过 React 的 Hooks API 触发状态更新)时,会执行渲染过程。即便组件并未实际挂载到页面上,React 也会递归计算组件的 JSX,这是为了构建虚拟 DOM 树,并跟踪 UI 的变化。以下是具体的过程:

  1. 组件执行与 Fiber 节点创建

    当 React 渲染一个组件时,React 内部会创建对应的 Fiber 节点。Fiber 是 React 中的工作单元,用于存储每个组件的状态、属性、子组件等信息。每一个函数组件(如 OperateLogModal)都会对应一个 Fiber 节点,Fiber 节点在首次渲染时会被创建,并且 React 会执行该函数以计算返回的 JSX。

  1. 执行组件函数,递归计算 JSX

    对于每个被渲染的组件(即使不在页面上显示),React 都会递归执行组件的函数体,并将每个子组件的 JSX 逐层解析。因此,即使 OperateLogModal 最终不在页面上显示,React 仍会执行该组件的函数体,包括 {getLogTable()},并将其作为子节点渲染到虚拟 DOM 中。

    在你的例子中:

    <Modal>
     {getLogTable()}
    </Modal>

    React 会递归调用 getLogTable,并将其返回的内容添加到 Modal 组件的子节点中。这样即使 Modal 最终未被挂载到实际的 DOM 中,getLogTable 已经被执行。

  1. forceRender 影响 DOM 挂载,但不影响渲染计算

    Antd Modal 的 forceRender 和 destroyOnClose 参数控制的是组件的实际 DOM 挂载行为。在 forceRender={false} 时,Ant Design 的 Modal 会在初始状态时避免将内容挂载到页面中;但 forceRender 不影响 React 在虚拟 DOM 中的构建过程。因此,React 会计算 Modal 的子节点,因此执行了 getLogTable。

  1. 避免不必要执行的源码级方法

    要控制这种行为,可以用 open && getLogTable(),React 会在 open 为 false 时跳过 getLogTable 的计算。这是因为在 && 短路运算中,React 不会渲染右侧的内容。这个原理在 React 的 beginWork 函数中体现:beginWork 会根据条件判断子组件是否需要更新,并跳过无效的分支。

新手上路,请多包涵

{

showOperationLogModal && <OperateLogModal showOperationLogModal={showOperationLogModal} />

}

推荐问题
宣传栏