Source:  Twitter logo

I'm accessing a promise that gets returned from my mock API. The React component looks like what you see below

import React from 'react';
import StudentListStatistics from './StudentListStatistics';
import StudentStatisticsApi from '../../api/mockStudentApi';

class AboutPage extends React.Component {
  constructor(props, context) {
      super(props, context);
      this.state = {
          studentsStatistics: []
      };

  }

componentDidMount() {
    StudentStatisticsApi.getAllStudentsStatistics().then(
        studentsStatistics => {
            this.setState({
                studentsStatistics: studentsStatistics

            });
            debugger;
        }
    );

    console.log(this.state.studentsStatistics);
}

render() {
    return (
        <div>
            <h2>Student Body Statistics</h2>
            <StudentListStatistics studentsStatistics={this.state.studentsStatistics}/>
        </div>
    );
}

the mock API looks like this

class StudentApi {
static getAllStudentsStatistics() {
    return new Promise((resolve, reject)=> {
        setTimeout(()=> {
            resolve(Object.assign([], studentsStatistics));
        }, 1000);
    });
}

I'm not sure why the this.state.studentsStatistics is always an empty array. If I step through the code then studentsStatistics array is being returned correctly from my mock API within the then callback.

Can someone point out what I might be missing.

The issue is two-fold:

  • getAllStudentsStatistics() is asynchronous, which means that it will eventually yield a result, but not immediately;
  • setState() is also "asynchronous", in that it won't change this.state immediately after it got called.

To work around that, and log the mocked data, you need to first wait for the promise to resolve, and then to also wait for setState to acknowledge that the state has changed (by passing it a callback function):

componentDidMount() {
  let promise = StudentStatisticsApi.getAllStudentsStatistics();

  promise.then(studentsStatistics => {
    this.setState({
      studentsStatistics: studentsStatistics
    }, () => {
      console.log(this.state.studentsStatistics);
    }
  });
}

I think this also means that your StudentListStatistics component will initially be rendered with an empty array as input. Only once the promise has been resolved will it receive the mocked data.

5 users liked answer #0dislike answer #05
robertklep profile pic
robertklep

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).