Why is using setState inside componentDidUpdate seen as a bad practice in React?

Viewed 353

I need to update a child's state when a prop gets updated, so I made something like this:

componentDidUpdate(prevProps) {
    const { searchValue, searchCriterion } = this.props;

    if (searchValue !== prevProps.searchValue) {
      this.setState({ searchValue });
    }
    if (searchCriterion !== prevProps.searchCriterion) {
      this.setState({ searchCriterion });
    }
  }

ESLint's airbnb guide is complaining about it and throwing this warning, even though I can't see any noticeable rendering or performance issues.

The warning says:

Updating the state after a component update will trigger a second render() call and can lead to property/layout thrashing.

Is there a better way to update a child's state when a prop has a new value?

Or should I ignore the warning?

1 Answers

The problem of your code is that it might create an infinite loop. When you call the setState method, you trigger a second render, just like the warning says, and consequently a new componentDidUpdate.

In order to solve this problem, you might want to create a break condition for certain values of your state to get out of your loop. For example, you could simply use a flag like so:

componentDidUpdate(prevProps) {
const { searchValue, searchCriterion } = this.props;

if (this.state.isAlreadyUpdated === true) {
  this.setState({ isAlreadyUpdated: false });
  break;
} else {
  this.setState({ isAlreadyUpdated: true });
}

if (searchValue !== prevProps.searchValue) {
  this.setState({ searchValue });
}
if (searchCriterion !== prevProps.searchCriterion) {
  this.setState({ searchValue });
}

}

Related