React在其属性发生变化时重新呈现整个组件

时间:2017-09-12 21:08:44

标签: reactjs

让我们考虑以下示例:

import React, {Component} from 'react';

class B extends Component {
  render() {
    console.log(`Render runs with ${this.props.paramA}`);
    return (<div>{this.props.paramA}</div> );
  }
}

class App extends Component {

  constructor() {
    super();
    this.state = {paramA: 'asd'};
  }

  handleChange(event) {
    this.setState({paramA: event.target.value});
  }

  render() {
    return (<div>
      <input value={this.state.paramA} onChange={e => this.handleChange(e)}/>
      <label>
      <B paramA={this.state.paramA}></B>
      </label>
    </div>);
  }
}

Here's the gif它是如何运作的。

如果您注意到,为了更新属性的更改,需要评估“渲染”方法。这导致整个组件更新而不是真正改变的小部分(检查gif,div元素在chrome开发人员工具中闪烁):

TL; DR 根据反应理念,应该以尽可能多的dummy组件的方式编写应用程序。这意味着我们有时必须将属性向下传递几级(其他时候我们可以使用例如redux),这会导致很多render方法在每次顶级组件的属性更改时进行评估。尽管如此,我经常在现实生活中看到应用程序,整个root div在例如...用户输入内容输入。好吧,即使它是一个浏览器“滞后”,我也不喜欢当一个组件只需要更新它的一小部分时,反应重新评估所有组件(意味着运行它们的渲染方法)的想法。

问题: 难道我做错了什么?有没有办法实现react组件,以便只更新发生变化的内容?

2 个答案:

答案 0 :(得分:1)

听起来你正在寻找shouldComponentUpdate生命周期钩子。

非常自我解释;如果组件只应在特定的prop / state更改下重新呈现,则可以在此钩子中指定它们,否则返回false。

答案 1 :(得分:1)

在这种情况下,React不会重新渲染整个组件,而是重新渲染它们的动态部分的第一个父组件。在这种情况下,<div>是父级(以及整个组件,所以你是对的),但是在段落标记中包含{this.props.paramA}的小提琴中,<div>不是直接父级,因此只需重新呈现<p>代码,而<div>不需要更新。

&#13;
&#13;
class B extends React.Component {
  render() {
    console.log(`Render runs with ${this.props.paramA}`);
    return (<div><p>{this.props.paramA}</p></div> );
  }
}

class App extends React.Component {

  constructor() {
    super();
    this.state = {paramA: 'asd'};
  }

  handleChange(event) {
    this.setState({paramA: event.target.value});
  }

  render() {
    return (<div>
      <input value={this.state.paramA} onChange={e => this.handleChange.bind(this)(e)}/>
      <label>
      <B paramA={this.state.paramA} />
      </label>
    </div>);
  }
};

ReactDOM.render(
  <App />,
  document.getElementById('container')
);
&#13;
<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>
<div id="container"></div>
&#13;
&#13;
&#13;