Render component after AJAX call ReactJS

Viewed 5340

I want to Render component after AJAX call. ReactJS

import React from 'react';
import { render } from 'react-dom';
import { Card } from './components/Card';

class App extends React.Component{
    constructor(){
        super();
        this.user = [];
        console.log("constructor");
}
    componentWillMount() {
        console.log("componentWillMount 1");
               $.ajax({
                   method:'get',
                   crossDomain: true,
                   url: "http://127.0.0.1:8000/product/"
               }).done(function(res) {
                   this.user=res;
                   console.log("componentWillMount 2");

               })
    }

    render(){
        var us = this.user
        console.log("render");
        return(
            <div className="container-fluid">
                <div className="container">
                    <div className="row">
                    {(function (rows, i, len) {
                        while (i <len) {
                            rows.push(<div className="col-sm-3">
                                <Card user={us[i]}/>
                                </div>)
                                i++
                        }
                        return rows;
                    })([], 0, us.length)}
                    </div>
                </div>
            </div>
        );
    }
}
render(<App/>,window.document.getElementById("app"));

I want in this order:

  • constructor
  • componentWillMount 1
  • componentWillMount 2
  • render

but its follow like this

  • constructor
  • componentWillMount 1
  • render
  • componentWillMount 2
1 Answers

Since you have an ASYNC request, its not guranteed that the request will complete before the component renders and hence you see the current behaviour. Also since after the request completes you are setting a class variable. It doesn't cause a rerender and even when the request completes the updates won't be visible. You need to make a few changes

First: Move the ASYNC request from componentWillMount to componentDidMount since you should setState with the response from API call to cause re-render and using setState in componentWillMount doesn't trigger a re-render

Second: Make use of arrow function in the .done callback of your ajax request as you need to bind it in order to access the class properties and function

class App extends React.Component{
    constructor(){
        super();
        this.state = {user: []};
        console.log("constructor");
}
    componentDidMount() {
        console.log("componentDidMount 1");
               $.ajax({
                   method:'get',
                   crossDomain: true,
                   url: "http://127.0.0.1:8000/product/"
               }).done((res) => {
                   this.setState({user:res});
                   console.log("componentDidMount 2");

               })
    }

    render(){
        var us = this.state.user
        console.log("render");
        return(
            <div className="container-fluid">
                <div className="container">
                    <div className="row">
                    {(function (rows, i, len) {
                        while (i <len) {
                            rows.push(<div className="col-sm-3">
                                <Card user={us[i]}/>
                                </div>)
                                i++
                        }
                        return rows;
                    })([], 0, us.length)}
                    </div>
                </div>
            </div>
        );
    }
}
render(<App/>,window.document.getElementById("app"));
Related