【问题标题】:When exactly is `componentDidMount` fired?`componentDidMount` 究竟是什么时候触发的?
【发布时间】:2016-03-17 00:24:36
【问题描述】:

这是我在使用 React 时经常遇到的问题。 componentDidMount 方法保证在第一次渲染组件时被触发,因此它似乎是一个自然的地方来进行 DOM 测量,如高度和偏移量。 但是,在组件生命周期的这个阶段,我多次收到错误的样式读数。当我与调试器中断时,组件 is 在 DOM 中,但尚未在屏幕上绘制。对于宽度/高度设置为 100% 的元素,我遇到了这个问题。 当我在 componentDidUpdate 中进行测量时 - 一切正常,但此方法不会在组件的初始渲染时触发。

所以我的问题是 - componentDidMount 究竟是什么时候被触发的,因为在所有浏览器绘制完成后它显然没有被触发。

编辑: This Stackoverflow issue 处理相同的主题:

它还引用了 this github conversation 来解释发生了什么

【问题讨论】:

标签: reactjs react-dom


【解决方案1】:

在 React 组件树中,componentDidMount() 在所有子组件都已安装后被触发。这意味着,任何组件的componentDidMount() 在其父组件被挂载之前被触发

因此,如果您想测量 DOM 位置和大小等,使用子组件的 componentDidMount() 是不安全的地方/时间来执行此操作。

在您的情况下:为了从 100% 宽度/高度组件中获得准确的读数,进行此类测量的安全位置将在 topcomponentDidMount() 内反应组件。
100% 是相对于父容器/容器的宽度/高度。因此,只有在安装父级之后才能进行测量。

【讨论】:

  • 这似乎回答了我的问题!但是,我对如何在安装父容器之前触发 componentDidMount 有点困惑。如果没有代表父级的 DOM 元素,那么组件的元素放在 DOM 的什么位置?
  • 恐怕有些搜索并没有为这个谜提供任何明显的答案。可能是因为反应在引擎盖下工作。我的猜测是父元素已经在 DOM 中,但只有在顶部组件内触发 componenDidMount() 后才能保证完成格式化。
  • 我也在尝试解决这个问题。当我研究时,我发现反应遵循一种称为“深度优先搜索”的图遍历方法。检查此视频。 youtube.com/watch?v=pcKY4hjDrxk
【解决方案2】:

如您所知,componentDidMount 仅在初始渲染后立即触发一次。

由于您正在进行测量,因此您似乎还希望在componentDidUpdate 时触发您的测量,以防您的测量在组件更新时发生变化。

请注意,componentDidUpdate 不会发生在初始渲染中,因此您可能需要两个生命周期事件来触发您的测量处理。看看这第二个事件是否会为您触发,以及它是否有不同的测量值。

在我看来,您应该尽可能避免使用setTimeoutrequestAnimationFrame

React Lifecycle Reference.

【讨论】:

    【解决方案3】:

    只在组件挂载时调用一次。这是执行异步请求以从 API 获取数据的最佳时机。获取的数据将 将其存储在内部组件状态中以在 render() 生命周期方法中显示。

    简单:它在渲染函数之后运行

    【讨论】:

      【解决方案4】:

      如果您想响应 DOM 中挂载的内容,最可靠的方法是使用 ref callback。例如:

      render() {
        return (
          <div
            ref={(el) => {
              if (el) {
                // el is the <div> in the DOM. Do your calculations here!
              }
            }}
          ></div>
        );  
      }
      

      【讨论】:

        【解决方案5】:

        您可以尝试使用requestAnimationFrame() 延迟componentDidMount() 中的逻辑。逻辑应该在下一次绘制之后发生。

        但是,我们需要更多地了解您的代码,以了解为什么节点没有被绘制。我从来没有遇到过这个问题。 componentDidMount() 在 dom 节点添加到页面后立即触发,但不一定在它们被绘制后触发。

        【讨论】:

          猜你喜欢
          • 2011-08-19
          • 1970-01-01
          • 2021-02-07
          • 2021-04-15
          • 2014-09-09
          • 2017-12-11
          • 2023-02-25
          • 2019-10-17
          • 2012-10-01
          相关资源
          最近更新 更多