Search code examples
javascriptjqueryfacebookreactjsreactjs-flux

How to wait to render view in react.js until $.get() is complete?


Hello I'm writing a chat client in reactjs and want to render my components with data retrieved from a REST call. However, my component is rendered before the REST request returns with data; this causes errors as I am calling this.props within my children components.

var MainChat = React.createClass({
getInitialData: function(){
    var c = []
    $.get("http://127.0.0.1:8888/test/sampledata.php?user=123", function(data, status) {
        console.log("Data: "+ data+ "\nStatus: " + status);
        c = data    
    })
},
getInitialState: function() {
    return {
        chatId : "",
        chats : this.getInitialData(),
        //chats: this.props.chats
    };
},
handleClickOnLeftUser: function(data){
    console.log("handleClickOnLeftUser");
    // console.log("chat id is"); 
    // console.log(data.chatID); 
    this.setState({chatID: data.chatID});
},

render: function() {
    console.log("main:render")
    console.log(this.props.chats);


    var theThreadIWantToPass = {};
    for(var i = 0; i < this.state.chats.length; i++)
    {
        console.log("chat: " + this.state.chats[i].chatID);
        if (this.state.chats[i].chatID === this.state.chatID) {
            theThreadIWantToPass = this.state.chats[i];
            break;
        }
    }

    return (
        <div className="chatapp">
            <div className="thread-section">
                <div className="thread-count">

                </div>
                <LeftUserList
                    chats={this.state.chats}
                    clickFunc={this.handleClickOnLeftUser} // ***important
                />
            </div>
            <div>
                <RightMessageBox chat={theThreadIWantToPass} />
            </div>
        </div>
    );
}
});

Solution

  • In your case you need use method componentDidMount, like so

    var MainChat = React.createClass({
    
      getInitialData: function() {
        var url = 'http://127.0.0.1:8888/test/sampledata.php?user=123';
    
        $.get(url, function(data, status) {
            this.setState({ chats: data });        
        }.bind(this))
      },
    
      componentDidMount: function () {
        this.getInitialData();
      },
    
      getInitialState: function() {
        return {
          chatId: '',
          chats: []
        };
      },
    
      handleClickOnLeftUser: function(data){
        this.setState({ chatID: data.chatID });
      },
    
      render: function() {
        var theThreadIWantToPass = {};
    
        for(var i = 0; i < this.state.chats.length; i++) {
          if (this.state.chats[i].chatID === this.state.chatID) {
            theThreadIWantToPass = this.state.chats[i];
            break;
          }
        }
    
        return (
          <div className="chatapp">
            <div className="thread-section">
              <div className="thread-count"></div>
              <LeftUserList
                  chats={this.state.chats}
                  clickFunc={this.handleClickOnLeftUser} />
            </div>
    
            <div>
              <RightMessageBox chat={theThreadIWantToPass} />
            </div>
          </div>
        );
      }
    });
    

    Note - using "async": false this is bad practice