Gvidas Pranauskas
Gvidas Pranauskas

Reputation: 109

React componentDidUpdate infinite loop even if the state matches

I am trying to update state whenever the component gets updated. I do so because I reuse the component to show different data from the API. But there is a problem - componentDidUpdate creates an infinite loop even though I check if the state is different from the response data.

I will add some code.

componentDidUpdate() {
    const { products } = this.state;
    axios
      .get(`http://localhost/wp-json/wp/v2/posts?categories=${this.props.match.params.id}`)
      .then(res => {
        if (res.data !== products) {
          this.setState({ products: res.data, loading: false });
        } else {
          console.log('matches');
        }
      })
      .catch(err => console.log(err));
  }

Is there any work-around to avoid making an API request every time the component gets updated? I have an API request in my componentDidMount function, but it works only for the initial render.

Upvotes: 0

Views: 191

Answers (4)

Sean Walsh
Sean Walsh

Reputation: 8354

res.data !== products is performing a reference check, which means it will always return true since res.data and products point to different objects in memory (unless axios keeps a cache of response objects, which I don't think it does).

One way to accomplish what you want would be to use the prevProps argument to componentDidUpdate in order to determine if props.match.params.id has changed:

componentDidUpdate(prevProps) {
    if (prevProps.match.params.id === this.props.match.params.id) {
        // no need to do anything since we're still on the same ID
        return;
    }

    // perform the rest of your fetching logic
}

Another option would be to perform a deep equality check using something like isEqual.

Upvotes: 1

kooskoos
kooskoos

Reputation: 4879

Rather than comparing the entire object/array which will always a different reference, compare some primitive data.

Something like an id should work fine or the length of array in a case where products are added or removed from the array.

Upvotes: 0

zouari
zouari

Reputation: 1077

You should use ComponentDidMount. In fact, you need to fetch the products list (a priori) only once.

Upvotes: 0

Juviro
Juviro

Reputation: 190

Unfortunately, comparing Objects in javascript is a little bit more complicated than comparing strings or numbers. In your example, you‘re not actually comparing if the objects are equal, but if the reference is equal, which is not the case.

Here is an example of comparing objects, that might work for you. But I would recommend, depending on how your res.data looks like, that you try to compare only some metrics instead of the whole objects, depending on which properties actually change.

Upvotes: 1

Related Questions