Kid_Learning_C
Kid_Learning_C

Reputation: 3603

react class component: how to wait until some code is finished and then render?

I have the following code that requests data from backend DB and load the results into a table on the web page.

import React, { Fragment } from 'react';
import MUIDataTable from 'mui-datatables';
import {tableColumns} from './TableColumns';
import api from '../utils/api';


class ReceivedHistoryTable extends React.Component {

  constructor(props){
    super(props);
    this.state = {
      columns: tableColumns,
      data: []
    };

    this.getTableData();
  }

  getTableData() {
    api.get('/project', {}).then(
      data => {
        const {issues, users} = data.project
        
        this.state.data = issues.map(function(issue){
          
          const u = users.find(user => user.id === issue.userIds[0])

          return [
            issue.title,
            issue.deadline,
            issue.status,
            issue.createdAt,
            (u && u.name) ? (u.name) : ('Not Assigned')
          ]
        })

        console.log('check 1: ', this.state.data)

      },
      
      error => {
        console.log(error)
      }
    );
  }

  
  render() {
    const { columns } = this.state;
    const options = {
      print: false,
      download: false,
      selectableRowsHideCheckboxes: true,
      selectableRows: 'None',
      filterType: "textField",
      responsive: 'stacked',
      rowsPerPage: 10,
      page: 1
    };

    console.log("check 2", this.state.data)

    return (
      <MUIDataTable
        title="My Table"
        data={this.state.data}
        columns={columns}
        options={options}
      />
    );
  }
}

export default ReceivedHistoryTable;

The problem is that even though there is valid data in the backend DB, as I can confirm by checking the console log console.log('check 1: ', this.state.data), the table component says that no data was available.

This was because when it renders and returns the MUIDataTable component, this.state.data is not loaded with data yet.

console.log("check 2", this.state.data) executes before console.log('check 1: ', this.state.data)

I'm struggling with 2 questions:

  1. How can I make sure that my component renders after this.getTableData(); finishes?
  2. Why my component does not re-render when after 0.1 second, this.state.data is updated with fetched data?

Upvotes: 0

Views: 886

Answers (3)

dc11
dc11

Reputation: 7

you can use setState, something like this (only when you get all the data the 'loading...' will change to your page):

componentDidMount(){
    this.getData();
}

getData = async() => {
    // get data from api
    this.setState({data: ...}, () => {
        // do something after the setState finished get data
        loader: false
    })
}

render(){
    return(
        {this.state.loader ? <>loading...</> : <div>your page</div>}
    );
}

Upvotes: 1

Nilanshu96
Nilanshu96

Reputation: 157

You can add a check to see if data is loaded and only then render the table like using a state variable or just checking if data array is empty. And always use this.setState for updating the state of a component. It does the work of informing React that an update is required.

Upvotes: 1

Steven
Steven

Reputation: 121

You should use this.setState() to let React know the state has changed.

  getTableData() {
    api.get('/project', {}).then(
      data => {
        const {issues, users} = data.project
        
        this.setState({data: issues.map(function(issue){
          
          const u = users.find(user => user.id === issue.userIds[0])

          return [
            issue.title,
            issue.deadline,
            issue.status,
            issue.createdAt,
            (u && u.name) ? (u.name) : ('Not Assigned')
          ]
        }));

        console.log('check 1: ', this.state.data)

      },
      
      error => {
        console.log(error)
      }
    );
  }

You shouldn't be modifying this.state directly. See https://reactjs.org/docs/state-and-lifecycle.html#do-not-modify-state-directly

Upvotes: 3

Related Questions