admin管理员组

文章数量:1399737

When using React I've understood it so that calling setState inside a ponent's render method is bad practice; instead keep this method pure. However, if I need to update the state based on an event that is linked to a ponent, how do I do this?

class Toggle extends React.Component {
   constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
       <button onClick={this.handleClick}>
         {this.state.isToggleOn ? 'ON' : 'OFF'}
       </button>
    );
  }
}

The code above is from React's official tutorial. As we can see, an eventhandler is bound to the onClick attribute, and inside this eventhandler the state of the ponent is changed, so potentially we will update the state while calling from a render method. Thus I am a bit lost as to why this is alright to do but not calling setState explicitly in the render method? Has it to do with how React wraps plain html-events?

When using React I've understood it so that calling setState inside a ponent's render method is bad practice; instead keep this method pure. However, if I need to update the state based on an event that is linked to a ponent, how do I do this?

class Toggle extends React.Component {
   constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
       <button onClick={this.handleClick}>
         {this.state.isToggleOn ? 'ON' : 'OFF'}
       </button>
    );
  }
}

The code above is from React's official tutorial. As we can see, an eventhandler is bound to the onClick attribute, and inside this eventhandler the state of the ponent is changed, so potentially we will update the state while calling from a render method. Thus I am a bit lost as to why this is alright to do but not calling setState explicitly in the render method? Has it to do with how React wraps plain html-events?

Share Improve this question asked Jul 24, 2018 at 11:31 tiggybitstiggybits 1191 silver badge9 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 3

What is bad practice is to call setState explicitly in the render method, because the render method should be able to run multiple times without having any side effects (Without affecting anything outside the render itself)

In the code block above, the setState is bound to a click handler, so that means it is only invoked when the button is clicked, not when the render method is called, so this is pletely fine.

To recap:

It is fine to have event handlers that update the state in the render method, as long as they are only called when that event is fired.

It is not good to have setState or a function that calls setState directly in the render function.

EXAMPLE

doSomthing = () => {
  this.setState({ foo: 'bar' });
}

render() {
  return (
    <button onClick={this.doSomething}>Click Me</button>
  );
}
// this code is GOOD

The above example is OK

doSomething = () => {
  this.setState({ foo: 'bar' });
}

render() {
  this.doSomething();
  return (
    <button>Click Me</button>
  );
}
// this code is BAD

The above example is BAD

render() {
    return (
       <button onClick={this.handleClick}>
         {this.state.isToggleOn ? 'ON' : 'OFF'}
       </button>
       {this.setState(() => ({}))}
    );
  }

When you are trying to do something like above. It causes rendering issue. Think what is the purpose of the setState(). Obviously to change the state of ponent. Now think what happens when your state changes. Yes your ponent is rendered again. Now think if a ponent is rendering and it finds the setState() again then it will cause the rendering to malfunction.

Now over to your issue of event handler a good practice of using setState()

It is simple concept, we are using reference in event call that means when the ponent is rendered it is not going to fire it immediately rather it will wait for someone to call. It is clear that when someone is going to invoke the call then only state is changed and it will cause no issue to render() and it will work properly

there is function not called, only passed :

<button onClick={this.handleClick}>
         {this.state.isToggleOn ? 'ON' : 'OFF'}
</button>

本文标签: javascriptCalling setState in an eventHandler in the render methodStack Overflow