bks4line
bks4line

Reputation: 515

ComponentDidUpdate SetState ReactJS Infinite loop

Even though there are many questions with the same subject line, I could not get an answer for my problem.

Problem

I have a select dropdown. On click of which, I call an Api which fetches some key values. I consider this set of key value input fields as a component. So each and every time onChange of my select drop-down, I have used lifecycle methods to handle API Calls. Also, I record these input key values and send back their state to parent component.

According to ReactJS lifecycle methods:

I use

componentDidMount To call the API for the first time after initial render. This works.

componentDidUpdate To call the API for subsequent API calls on select drop-down change. But here is the problem. When I try to update the state of input fields the program falls into an infinite loop and hence there are infinite API calls. I am pretty sure after debugging that the problem is with setState(), But I couldnt find the best way to handle states in componentDidUpdate method.

This link exactly replicates my problem but i want a standardized solution

Hope this is clear. Thanks for the help in advance!

Upvotes: 4

Views: 11343

Answers (5)

Arin Yazilim
Arin Yazilim

Reputation: 1117

You have to check the real difference between two state objects. Below you can find my solution, My state object has movies, which is an array of objects. I edited and movie and then comparing these two arrays.

    async componentDidUpdate(prevProps, prevState) {

        if (prevState.movies.filter (e => this.state.movies.includes(e))) {
        const response = await axios.get("http://localhost:3002/movies");
        this.setState({ movies: response.data })
    }
}

Upvotes: 0

Pramuditha
Pramuditha

Reputation: 738

You can use setState() within componentDidUpdate(). But you have to use the condition for that. Otherwise, it get infinite loop.

As the example,

 componentDidUpdate(){
    if(this.props.id !== this.state.id) {
        this.setState({
            id: this.props.id 
        });
    }
 }

Upvotes: 2

Madbreaks
Madbreaks

Reputation: 19549

This is spelled out pretty clearly in the docs:

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you’ll cause an infinite loop.

Upvotes: 7

Ajay B
Ajay B

Reputation: 23

This happens because setState triggers a call to componentDidUpdate.

When componentDidUpdate is called, setState does not check whether or not state change has occurred. It simply calls componentDidUpdate again and again, which leads to stackoverflow.

  class Component extends React.Component{
    constructor(props){
      super(props);
      this.state = {changeState: false}
    }
    componentDidMount(){
      this.setState({changeState: true});
    }
    componentDidUpdate(){
        this.setState({changeState: false});
    } 
 }

Here, first changeState is set to false in constructor, and then componentDidMount is triggered, which sets state of changeState to true. This state change triggers componentDidUpdate, which sets the state of changeState again to true. This triggers componentDidUpdate again and again.

Upvotes: 0

Debabrata Mohanta
Debabrata Mohanta

Reputation: 645

Yes you cannot setState() inside componentDidUpdate it would lead to infinite loop.Instead you can call a function onChange event and change the state there.

Upvotes: 0

Related Questions