【问题标题】:React - Parent component DidMount earlier than childrenReact - 父组件 DidMount 早于子组件
【发布时间】:2017-03-27 10:25:33
【问题描述】:

直到现在,我一直认为 React 生命周期是这样工作的:

<ComponentA>
  <ComponentB />
</ComponentA>
  1. 组件A(组件WillMount)

    1.1。组件B(组件WillMount)

    1.2:组件B(componentDidMount)

  2. ComponentA (componentDidMount)

因此,父级总是必须等待子级被渲染才能完成 DidMount 状态。

但是,我发现在我拥有的复杂组件上,这不会发生。

它调用:

  1. 组件A (componentWillMount)

  2. ComponentA (componentDidMount)

  3. ComponentB (componentWillMount)

  4. ComponentB (componentDidMount)

这真的会发生吗? (或者我可能做错了什么)

如果 ComponentA 渲染而没有渲染它的子级 (ComponentB),它应该在 DOM 中是什么?

【问题讨论】:

  • 你能在 jsfiddle/codepen 中重现这个吗?
  • 别这么认为,它有很多代码。这不是一个简单的示例代码,这就是为什么我做了通用问题,以确保这是否是预期的行为。对不起:(
  • 从技术上讲,生命周期方法仅保证您的特定组件已安装。它没有对它的孩子做出任何承诺。依赖此顺序通常表明您正在打破组件的封装边界。例如,如果您的组件渲染另一个组件,该组件可能会选择在加载数据时延迟渲染它的子组件(即使它们是从上面传递的)。

标签: reactjs


【解决方案1】:

经过努力调试,发现问题出在哪里:

我正在使用 SizeMe HOC 的其中一个儿童组件。

阅读该库的源代码,我检查了它的渲染创建“WrappedComponent”或“PlaceHolder”。 因此,它正在创建这个 PlaceHolder,使该组件被认为是 Mounted,但它还没有渲染我真正的孩子。

这里可以看到SizeMe.js code:

/**
 * As we need to maintain a ref on the root node that is rendered within our
 * SizeMe component we need to wrap our entire render in a sub component.
 * Without this, we lose the DOM ref after the placeholder is removed from
 * the render and the actual component is rendered.
 * It took me forever to figure this out, so tread extra careful on this one!
 */
const renderWrapper = (WrappedComponent) => {
  function SizeMeRenderer(props) {
    const {
      explicitRef,
      className,
      style,
      size,
      disablePlaceholder,
      ...restProps,
    } = props;
    const { width, height } = size;

    const toRender = (width === undefined && height === undefined && !disablePlaceholder)
      ? <Placeholder className={className} style={style} />
    : <WrappedComponent className={className} style={style} size={size} {...restProps} />;

    return (
      <ReferenceWrapper ref={explicitRef}>
        {toRender}
      </ReferenceWrapper>
    );
  }
  ...

所以,我可以假设是的,生命周期顺序就像我在第一个实例中假设的那样工作

【讨论】:

  • 谢谢....遇到了同样的问题。看起来如果您在 sizeMe 选项中传递 noPlaceholder=true ,它将首先呈现孩子。
【解决方案2】:

我很好奇,所以我整理了一个simple example in jsfiddle

var Container = React.createClass({
  componentWillMount: function() {
    return console.log("Container will mount");
  },
  componentDidMount: function() {
    return console.log("Container did mount");
  },
  render: function() {
    return <div>{this.props.children}</div>;
  }
});

var Child = React.createClass({
  componentWillMount: function() {
    return console.log("Child will mount");
  },
  componentDidMount: function() {
    return console.log("Child did mount");
  },
  render: function() {
    return <div> Hello World </div>;
  }
});


ReactDOM.render(
  <Container>
    <Child />
  </Container>,
  document.getElementById('container')
);

这会产生输出

容器将挂载

孩子会坐骑

孩子确实骑马

容器确实挂载了

这符合您最初的期望。

不确定这是否对您有帮助。

【讨论】:

  • 我很久以前就已经测试过了,以确保它可以这样工作。但无论如何谢谢:)我已经发现发生了什么! :)
猜你喜欢
  • 2019-08-15
  • 2018-07-30
  • 1970-01-01
  • 2023-04-10
  • 2019-03-11
  • 2018-09-04
  • 2021-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多