Search code examples
javascriptarraysreactjssetstate

React componentDidMount() initializing state


Working on a small project in React, and I'm using Axios to grab information from an API that is tested working. The problem is when I pull in the data and try to update the component state, the values coming in from the API aren't getting filled into the state to be rendered in the component.

I've been trying to get the data in the state like so:

  componentDidMount() {
    this.state.databases.forEach(d => {
      axios.get(`http://localhost:3204/customer/${d}/count`).then(value => {
        this.setState({ counts: this.state.counts.push(value.data) });
      });
    });
    console.log(this.state);
  }

a previous version was written like so:

componentDidMount() {
    let internalCounts = [];
    this.state.databases.forEach(d => {
        axios.get(`http://localhost:3204/customer/${d}/count`).then(value => {
            internalCounts.push(value.data);
        });
    });
    this.setState({count: internalCounts});
}

Both situations end up with the same result. The state is never really updated with the new count array. I have the suspicion that this is due to the async nature of Axios and setState.

What would be a simple, effective way to get these two to stop racing each other?


Solution

  • Don't use console.log immediately after setting the state since it is asynchronous. Do it with a callback to setState.

    this.setState({...}, () => console.log(...))
    

    or inspect your state in your render method with console.log

    Also, rather than doing it forEach, try to make all the request in one time with Promise.all if this suits you.

    componentDidMount() {
        const promiseArray = this.state.databases.map( d =>
          axios.get(`http://localhost:3204/${d}/count`)
        )
        Promise.all( promiseArray )
          .then( ( results ) => {
            const data = results.map( result => result.data);
            this.setState( prevState => ({
              counts: [ ...prevState.counts, ...data]
            }))
          })
      }