Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

componentWillMount does not finish before render

Tags:

reactjs

I am facing some difficulties regarding to state in reactjs. As far as I know componentWillMount is a place to load the data with ajax call before the components get rendered. I have a simple simple project which populates stack of panels with a loaded data and show it on board. However the data from ajax call do not get set before rendering of the component and this leads to rendering of the board with an empty array. The follwoing is my complete source:

import  React from "react";
export class Panel extends  React.Component{
render() {
    return (
    <div>
        <div className="row panel">
            <div className="col-sm-12 header">sfsfsf</div>
            <div className="col-sm-12 body">fsdfsfs</div>
            <div className="col-sm-12 footer">fasfaf</div>
        </div>
    </div>
    );
   }
   }

and Board class which is a root of the problem is as follows :

import  React from "react";
 import {Panel} from "./Panel";
 export class Board extends  React.Component{
 constructor(props){
    super();
    this.state={news: []};
}
componentWillMount(){
    this.state={news: []};
    $.ajax({
        url: "http://localhost:3003/json.txt",
        dataType: 'json',
        cache: false,
        success: function(data) {
            var arr=[];
            for (var key in data) {
                arr.push(data[key]);
                console.log(data[key]);
            }
            this.state={news: arr};
        }});
     }
     render() {
    return (
        <div>
            {
                this.state.news.map((item,i)=> <Panel key="i"/>)
            }
        </div>
    );
    }
 }

Also the last class is index.js:

import React from "react";
 import {render} from "react-dom";
import {Board} from "./component/Board";

class App extends React.Component{

  render(){
    return(
        <div>

            <Board/>

        </div>

    );
  }

}

 render(<App/>, document.getElementById('middle'));

So as you can see in the Board.js class I initialize my array in render function and then I use componentWillMount to fill the news array which I expect it to happen after componentWillMount is finished but in my case the array is empty when rendering happens. Any idea?

*********UPDATE***************

I also tried it with componentDidMount but it did not work and the same problem

like image 812
Hamed Minaee Avatar asked Nov 05 '25 05:11

Hamed Minaee


2 Answers

componentWillMount() is finishing before render but because ajax is async it will not execute until the request completes.

You should not set state using this.state = .... Instead use:

this.setState({news: arr});

This will set the value and trigger the component and all children to render. Just write your render function to handle null data nicely and you'll have your expected result without blocking JS execution.

As suggested here it is with proper binding:

import  React from "react";
import {Panel} from "./Panel";
export class Board extends  React.Component{
  constructor(props){
    super();
  }

  getInitialState() {
    return {news: []};
  }

  componentWillMount(){
    $.ajax({
      url: "http://localhost:3003/json.txt",
      dataType: 'json',
      cache: false,
      success: (data) => {
        var arr=[];
        for (var key in data) {
          arr.push(data[key]);
          console.log(data[key]);
        }
        this.setState({news: arr});
      }
    });
  }
  render() {
    return (
        <div>
            {
                this.state.news.map((item,i)=> <Panel key="i"/>)
            }
        </div>
    );
  }
}

The arrow function handles the binding. Simmilar to function(){}.bind(this)

like image 58
Rob Lynch Avatar answered Nov 07 '25 01:11

Rob Lynch


You are doing a ajax call which is async... By definition it will continue to execute the code without waiting for the ajax's response.

you can turn that synchronous by setting async: false on the $.ajax options.

like image 30
Lucas Katayama Avatar answered Nov 07 '25 03:11

Lucas Katayama



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!