【问题标题】:React: Why component's constructor is called only once?React:为什么组件的构造函数只被调用一次?
【发布时间】:2015-03-16 10:36:31
【问题描述】:

following example 中,当点击Item 2 时,会显示Second 1 而不是Second 2。为什么?你会如何解决这个问题?


var guid = 0;

class Content extends React.Component {
  constructor() {
    guid += 1;
    this.id = guid;
    console.log('ctor', this.id); // called only once with 1
  }
  render() {
    return (
      <div className="content">
        {this.props.title} - {this.id}
      </div>
    );
  }
}

class MyApp extends React.Component {
  constructor() {
    this.items = ['Item 1', 'Item 2'];
    this.state = {
      activeItem: this.items[0]
    };
  }
  onItemClick(item) {
    this.setState({
      activeItem: item
    });
  }
  renderMenu() {
    return (
      <div className="menu">
        <div onClick={this.onItemClick.bind(this, 'Item 1')}>Item 1</div>
        <div onClick={this.onItemClick.bind(this, 'Item 2')}>Item 2</div>
      </div>
    );
  }
  renderContent() {
    if (this.state.activeItem === 'Item 1') {
      return (
        <Content title="First" />
      );
    } else {
      return (
        <Content title="Second" />
      );
    }
  }
  render() {
    return (
      <div>
        {this.renderMenu()}
        {this.renderContent()}
      </div>
    );
  }
}

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    React 的 reconciliation algorithm 假设在没有任何相反信息的情况下,如果自定义组件在后续渲染中出现在同一位置,则它与以前的组件相同,因此重用前一个实例而不是创建新实例。

    如果你要实现componentWillReceiveProps(nextProps),你会看到它被调用了。

    Different Node Types

    &lt;Header&gt; 元素不太可能生成一个看起来像&lt;Content&gt; 生成的 DOM。 React 没有花时间尝试匹配这两个结构,而是从头开始重新构建树。

    作为推论,如果在两个连续渲染中的同一位置有一个 &lt;Header&gt; 元素,您会期望看到非常相似的结构,值得探索。

    Custom Components

    我们决定这两个自定义组件是相同的。由于组件是有状态的,我们不能只使用新组件就可以收工。 React 从新组件中获取所有属性,并在前一个组件上调用 component[Will/Did]ReceiveProps()

    之前的组件现在可以运行了。它的render() 方法被调用,diff 算法以新结果和之前的结果重新开始。

    如果您为每个组件指定 a unique key prop,React 可以使用 key 更改来推断该组件实际上已被替换,并将从头开始创建一个新组件,从而为其提供完整的组件生命周期。


      renderContent() {
        if (this.state.activeItem === 'Item 1') {
          return (
            <Content title="First" key="first" />
          );
        } else {
          return (
            <Content title="Second" key="second" />
          );
        }
      }
    

    【讨论】:

    猜你喜欢
    • 2013-12-11
    • 2022-07-05
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多