【问题标题】:In which order are parent-child components rendered?父子组件按什么顺序呈现?
【发布时间】:2017-11-23 02:40:16
【问题描述】:

如果我有两个这样的组件(父母和孩子):

1-父母(倒计时):

var Countdown = React.createClass({
  getInitialState: function(){
    return{count: 0};
  },
  handleSetCountdown: function(seconds){
    this.setState({
      count: seconds
    });
  },
  render:function(){
    var {count} = this.state;
    return(
      <div>
        <Clock totalSeconds={count}/>
        <CountdownForm onSetCountdown={this.handleSetCountdown} />
      </div>
    );
  }
});

module.exports =Countdown;

2-The Child (CountdownForm):

var CountdownForm = React.createClass({
  onSubmit: function(e){
    e.preventDefault();
    var strSeconds = this.refs.seconds.value;
    if(strSeconds.match(/^[0-9]*$/)){
      this.refs.seconds.value ='';
      this.props.onSetCountdown(parseInt(strSeconds,10));

    }
  },
  render: function(){
    return(
      <div>
        <form ref="form" onSubmit={this.onSubmit} className="countdown-form">
          <input type="text" ref="seconds" placeholder="Enter Time In Seconds"/>
          <button className="button expanded">Start</button>
        </form>
      </div>
    );
  }
});

module.exports = CountdownForm;

我对生命周期(渲染组件的顺序)感到困惑?

【问题讨论】:

    标签: javascript html reactjs dom jsx


    【解决方案1】:

    我没有立即在 React 文档中看到明确的“这是父子之间的生命周期事件的顺序”,尽管我可能会错过它。

    当然,凭经验确定是微不足道的:

    class Child extends React.Component {
        constructor(...args) {
            super(...args);
            console.log("Child constructor");
        }
        componentWillMount(...args) {
            console.log("Child componentWillMount");
        }
        componentDidMount(...args) {
            console.log("Child componentDidMount");
        }
        render() {
            console.log("Child render");
            return <div>Hi there</div>;
        }
    }
    
    class Parent extends React.Component {
        constructor(...args) {
            super(...args);
            console.log("Parent constructor");
        }
        componentWillMount(...args) {
            console.log("Parent componentWillMount");
        }
        componentDidMount(...args) {
            console.log("Parent componentDidMount");
        }
        render() {
            console.log("Parent render start");
            const c = <Child />;
            console.log("Parent render end");
            return c;
        }
    }
    
    ReactDOM.render(<Parent />, document.getElementById("react"));
    .as-console-wrapper {
      max-height: 100% !important;
    }
    <div id="react"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

    这显示了我们的顺序:

    父构造函数 父组件WillMount 父渲染开始 父渲染结束 子构造函数 子组件WillMount 子渲染 子组件DidMount 父组件DidMount

    这让我想知道父母中孩子的顺序,所以:

    class Child extends React.Component {
        constructor(props, ...rest) {
            super(props, ...rest);
            console.log(this.props.name + " constructor");
        }
        componentWillMount(...args) {
            console.log(this.props.name + " componentWillMount");
        }
        componentDidMount(...args) {
            console.log(this.props.name + " componentDidMount");
        }
        render() {
            console.log(this.props.name + " render");
            return <div>Hi from {this.props.name}!</div>;
        }
    }
    
    class Parent extends React.Component {
        constructor(...args) {
            super(...args);
            console.log("Parent constructor");
        }
        componentWillMount(...args) {
            console.log("Parent componentWillMount");
        }
        componentDidMount(...args) {
            console.log("Parent componentDidMount");
        }
        render() {
            console.log("Parent render start");
            const result =
                <div>
                    <Child name="Child1" />
                    <Child name="Child2" />
                </div>;
            console.log("Parent render end");
            return result;
        }
    }
    
    ReactDOM.render(<Parent />, document.getElementById("react"));
    .as-console-wrapper {
      max-height: 100% !important;
    }
    <div id="react"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

    这给了我们:

    父构造函数 父组件WillMount 父渲染开始 父渲染结束 Child1 构造函数 Child1 组件WillMount Child1 渲染 Child2 构造函数 Child2 组件WillMount Child2 渲染 Child1 组件DidMount Child2 组件DidMount 父组件DidMount

    一点也不奇怪,但最好仔细检查一下。 :-)

    【讨论】:

      【解决方案2】:

      只需将componentWillUnmount添加到循环中:

      class Child extends React.Component {
          constructor(props, ...rest) {
              super(props, ...rest);
              console.log(this.props.name + " constructor");
          }
          componentWillMount(...args) {
              console.log(this.props.name + " componentWillMount");
          }
          componentWillUnmount(...args) {
              console.log(this.props.name + " componentWillUnmount");
          }
          componentDidMount(...args) {
              console.log(this.props.name + " componentDidMount");
          }
          render() {
              console.log(this.props.name + " render");
              return <div>Hi from {this.props.name}!</div>;
          }
      }
      
      class Parent extends React.Component {
          constructor(...args) {
              super(...args);
              console.log("Parent constructor");
          }
          componentWillMount(...args) {
              console.log("Parent componentWillMount");
          }
          componentWillUnmount(...args) {
              console.log("Parent componentWillUnmount");
          }
          componentDidMount(...args) {
              console.log("Parent componentDidMount");
          }
          render() {
              console.log("Parent render start");
              const result =
                  <div>
                      <Child name="Child1" />
                      <Child name="Child2" />
                  </div>;
              console.log("Parent render end");
              return result;
          }
      }
      
      class ParentWrapper extends React.Component {
          constructor(...args) {
              super(...args);
              this.state = { showParent: true };
              setTimeout(() => { this.setState({ showParent: false }) });
          }
          render() {
              return <div>{this.state.showParent ? <Parent /> : ''}</div>;
          }
      }
      
      ReactDOM.render(<ParentWrapper />, document.getElementById("react"));
      .as-console-wrapper {
        max-height: 100% !important;
      }
      <div id="react"></div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

      结果:

      Parent constructor
      Parent componentWillMount
      Parent render start
      Parent render end
      Child1 constructor
      Child1 componentWillMount
      Child1 render
      Child2 constructor
      Child2 componentWillMount
      Child2 render
      Child1 componentDidMount
      Child2 componentDidMount
      Parent componentDidMount
      Parent componentWillUnmount
      Child1 componentWillUnmount
      Child2 componentWillUnmount
      

      【讨论】:

        【解决方案3】:

        现场演示

        react-parent-child-lifecycle-order

        https://33qrr.csb.app/

        https://codesandbox.io/s/react-parent-child-lifecycle-order-33qrr

        创建订单

        
        parent constructor
        parent WillMount
        parent render
        
        child constructor
        child WillMount
        child render
        child DidMount
        
        parent DidMount
        
        

        破坏秩序

        parent WillUnmount
        
        child WillUnmount
        
        // child unmount
        
        // parent unmount
        
        
        
        

        【讨论】:

          【解决方案4】:

          render order是按照react组件树的顺序执行的,但是mount order是相反的(最里面的子组件挂载首先。)

          【讨论】:

            【解决方案5】:

            可以使父级的 ComponentDidMount 方法在子级的 ComponentDidMount 方法之前执行。 下面是它的完成方式。

            在父级的第一个 div 中,在渲染任何内容之前,检查状态是否已设置。仅在设置状态时才渲染任何内容。

            例子:

            render() {
              const { t } = this.props;
              return (
                <div>
                  {this.state.row !== null ? (
                        ...
                  ) : null}
                </div>
              );
            }
            

            【讨论】:

              猜你喜欢
              • 2020-03-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-02-09
              • 1970-01-01
              • 1970-01-01
              • 2013-09-29
              相关资源
              最近更新 更多