calling setState method with other statements

Viewed 165

I know that calling setState method means I don’t have to manually invoke the ReactDOM.render method. Below is some example code:

...
render() {
        return (
            <button onClick={this.handleClick}>  
               Click
            </button>
        )
    }

    handleClick = () => {
        this.setState({ counter: this.state.counter + 1 }, () => this.setState({ hasButtonBeenClicked: this.state.counter > 0 }));
        this.props.callback();
    }

since there is another statement this.props.callback(); below the this.setState() method, so does ReactDOM.render method get called before or after this.props.callback();?

2 Answers

since there is another statement this.props.callback(); below the this.setState() method, so does ReactDOM.render method get called before or after this.props.callback();?

After, in your case. The state update and call to render is asynchronous if setState is called within a React event handler (and may be asynchronous even if not, more here). The sequence (within a React event handler) is:

  1. You call setState with the state update.
  2. You call this.props.callback();
  3. React processes the state update (possibly combining it with other pending updates).
  4. (Some handwaving here about shouldComponentUpdate.)
  5. React calls render to have it render the current state.

If you want this.props.callback(); called after the new state has been rendered, put it in a function as the second argument of setState:

handleClick = () => {
    this.setState(
        { counter: this.state.counter + 1 },
        () => {
            this.props.callback();
        }
    );
}

or

handleClick = () => {
    this.setState(
        { counter: this.state.counter + 1 },
        this.props.callback
    );
}

...if this.props.callback doesn't care what this you call it with.

More here:

If you look at my example of your code, this.props.callback() gets called immediately after the state has been updated.

handleClick = () => {
        this.setState({ counter: this.state.counter + 1, hasButtonBeenClicked: true }, () => this.props.callback() );
    }

You have chained setStates, which seem unnecessary for readability. These should be grouped into a single setState call automatically, however one is nested into the callback and this would trigger multiple re-renders.. depending on ShouldComponentUpdate.

To avoid guessing or leaving it susceptible to future React updates: Using the setState callback for this.props.callback, is the best way to ensure it is executed after setState completes.

Updated, based on T.J Crowders feedback and research with event handlers: The way your code was structured it is most probable that this.props.callback will be called prior to the setState actually completing state updates, it will trigger the re-render once state updates.

-Because, it is in an asynchronous call and within a React event handler. SetState should update state after.(I am still no expert on promises, and have to wonder if there is a chance state could update within the millisecond, depending on your browsers internal clock and the batch processing)

For clarity, to others. This example is asynchronous and that means the code continues to be executed, while waiting for resolution. While setState returns a promise. In this case, it should absolutely continue to process this.props.callback(), until the promise is resolved.

Related