首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >当道具没有改变时,为什么调用子组件的渲染?

当道具没有改变时,为什么调用子组件的渲染?
EN

Stack Overflow用户
提问于 2019-06-13 06:17:39
回答 3查看 121关注 0票数 2
代码语言:javascript
复制
 // Child component
 class Button extends React.Component {
    render() {
      console.log("Render of Button called");
      return (
        <button onClick={this.props.handleClick}>
          {this.props.children}
        </button>
      );
    }
  }

 // Parent component
  class ButtonRenderer extends React.Component {
    state = {
      count: 0
    };
    increment() {
      this.setState({
        count: this.state.count + 1
      });
    }
    render() {
      console.log("Render of ButtonRenderer called.");
      return (
        <div>
          <Button handleClick={this.increment.bind(this)}>Click me</Button>
          <div>Count: {this.state.count}</div>
        </div>
      );
    }
  }

  function init() {
    var rootElement = document.getElementById("root");
    const childElement = <ButtonRenderer />;
    ReactDOM.render(childElement, rootElement);
  }

每次单击该按钮,父组件中的状态都会更改,因此将随子组件Button.render一起调用ButtonRenderer.render。为什么?

我尝试了所有3种调用事件处理程序的方法:

使用内联绑定()的

  1. 。与上面的代码相同。
  2. 类属性:

代码语言:javascript
复制
... 
increment = () => {
  this.setState({
    count: ++this.state.count
  });
}
...
 <Button handleClick={this.increment}>Click me</Button>
...

  1. 内联箭头函数。

代码语言:javascript
复制
... 
increment(){
  this.setState({
    count: ++this.state.count
  });
}
...
<Button handleClick={() => {this.increment();}}>Click me</Button>
...

对于每一次单击,所有3种方法都会执行这两个

方法。

我希望approach1和approach2不会在每次单击时都调用Button的render方法,因为没有任何变化。我希望approach3在每次点击时都会调用Button的render方法,因为我使用的是内联箭头函数,它将为每个render for ButtonRendered类创建一个新函数。

每次单击按钮时的浏览器控制台输出:

代码语言:javascript
复制
Render of ButtonRenderer called.
Render of Button called

我的问题是:当没有专业人员更改为Button comp时,为什么approach1 (使用bind)和approach2(使用类属性)都在调用子组件Button的render()方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-06-13 06:34:39

如果要避免不需要的渲染,请使用PureComponent

代码语言:javascript
复制
// Child component
 class Button extends React.PureComponent {
    render() {
      console.log("Render of Button called");
      return (
        <button onClick={this.props.handleClick}>
          {this.props.children}
        </button>
      );
    }
  }

 // Parent component
  class ButtonRenderer extends React.Component {
    state = {
      count: 0
    };
    increment = () => {
      this.setState({
        count: this.state.count + 1
      });
    }
    render() {
      console.log("Render of ButtonRenderer called.");
      return (
        <div>
          <Button handleClick={this.increment}>Click me</Button>
          <div>Count: {this.state.count}</div>
        </div>
      );
    }
  }

  function init() {
    var rootElement = document.getElementById("root");
    const childElement = <ButtonRenderer />;
    ReactDOM.render(childElement, rootElement);
  }
  init();
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

票数 2
EN

Stack Overflow用户

发布于 2019-06-13 06:33:57

如果父组件被更新,React是否总是更新该组件中的所有直接子组件?

不是的。仅当shouldComponentUpdate()返回true时,React才会重新呈现组件。默认情况下,该方法总是返回true,以避免新手出现任何细微的bug(正如William B所指出的,DOM实际上不会更新,除非发生了更改,从而降低了影响)。Font

实际上,默认情况下,子组件将始终重新呈现,除非您显式地告诉then不这样做。应该在这里实现shouldComponentUpdate,以防止不必要的渲染,除非属性值发生变化。或者使用PureComponent

票数 1
EN

Stack Overflow用户

发布于 2019-06-13 06:43:59

解决方案# 1。

代码语言:javascript
复制
    // Parent component
    class ButtonRenderer extends React.Component {
      state = {
        count: 0
      };
      increment = () => {
        this.setState({
          count: ++this.state.count
        });
      }
      render() {
        console.log("Render of ButtonRenderer called.");
        return (
          <div>
            <Button handleClick={this.increment}>Click me</Button>
            <div>Count: {this.state.count}</div>
          </div>
        );
      }
    }

您可以通过在shouldComponentUpdate方法中返回false来避免更新。您还可以在其中编写业务登录,并根据它返回falsetrue

代码语言:javascript
复制
        // Child component
    class Button extends React.PureComponent {
      constructor (props) {
        super(props)
      }
      render() {
        console.log("Render of Button called");
        return (
          <button onClick={this.props.handleClick}>
            {this.props.children}
          </button>
        );
      }
    }

    // Parent component
    class ButtonRenderer extends React.Component {
      state = {
        count: 0
      };
      increment = () => {
        this.setState({
          count: ++this.state.count
        });
      }
      render() {
        console.log("Render of ButtonRenderer called.");
        return (
          <div>
            <Button handleClick={this.increment}>Click me</Button>
            <div>Count: {this.state.count}</div>
          </div>
        );
      }
    }

当你扩展到React.PureComponent而不是React.Component时,一些生命周期方法。在这种情况下,这是可行的。

如果你对我的回答有帮助,请考虑投赞成票。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56571069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档