V
V
Vladimir Golub2019-02-24 01:16:47
React
Vladimir Golub, 2019-02-24 01:16:47

Error Maximum update depth exceeded?

I get this data using fetch with componentDidMount after I update the state, the counter is updated to update the state. API paginated.

getFilms = (str) => {
    fetch(str)
      .then(
          response => response.json()
      ).then(data => {
        ...

        this.setState(prevState => ({
          people: [ ...prevState.people, ...dataArr],
          count: prevState.count + countItems,
          linkSource: data.next
        }));
      })
  };

  getGenderCount = () => {
    let genderCount = {
      male: 0,
      female: 0,
      middle: 0
    };

    let people = this.state.people.slice();

    people.forEach(peopleItem => {
      if (peopleItem.gender === "male") {
        genderCount.male++;
      }
      else if (peopleItem.gender === "female") {
        genderCount.female++;
      }
      else if (peopleItem.gender === "n/a") {
        genderCount.middle++;
      }
    });
    
    this.setState(() => (
      {
        genderCount: {
          male: genderCount.male,
          female: genderCount.female,
          middle: genderCount.middle
        }
      })
    );
  };

  componentDidMount() {
    this.getFilms('https://swapi.co/api/people/');
  }

  componentDidUpdate() {
    this.getGenderCount();

    if (this.state.linkSource && this.state.count < this.state.maxCount) {
      this.getFilms(this.state.linkSource);
    }
  }

Answer the question

In order to leave comments, you need to log in

1 answer(s)
0
0xD34F, 2019-02-24
@RazerVG

When you update the component, you call the getGenderCount method, which calls setState, causing componentDidUpdate to fire again, calling getGenderCount - setState - compoenentDidUpdate again, repeating ad infinitum (no, that's why you're here).
Probably, the getGenderCount method should be called not every time the component is updated, but when some conditions are met (think about which ones).

UPD. What would your code look like.
class App extends React.Component {
  state = {
    maxCount: 55,
    people: [],
    url: 'https://swapi.dev/api/people/',
  }

  fetchPeople() {
    fetch(this.state.url).then(r => r.json()).then(r => {
      this.setState(({ people, maxCount }) => ({
        people: [ ...people, ...r.results ].slice(0, maxCount),
        url: r.next,
      }));
    });
  }

  updateGenderCount() {
    this.setState(({ people }) => ({
      genderCount: people.reduce((acc, n) => {
        acc[n.gender] = (acc[n.gender] || 0) + 1;
        return acc;
      }, {}),
    }));
  }

  componentDidMount() {
    this.fetchPeople();
  }

  componentDidUpdate(prevProps, prevState) {
    const count = this.state.people.length;
    if (count !== prevState.people.length) {
      this.updateGenderCount();

      if (this.state.url && count < this.state.maxCount) {
        this.fetchPeople();
      }
    }
  }

  render() {
    return (
      <div>
        <pre>{JSON.stringify(this.state.genderCount, null, 2)}</pre>
      </div>
    );
  }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question