24

I am new to ReactJS and trying to understand it. Now I have a situation where I am loading information needed for rendering. But as it is asynchronous the component renders itself before the information is passed to it.

var info;

function getInfo() {
    //this will come from backend REST with Backbone which takes a bit
}

var InfoPage = React.createClass({
    render: function() {        
        getInfo()

        return (
            <div>info: {info}</div>            
        );
    }
});

Now the div will not show the info-value as it is not yet set in the render. So how can I have get render to wait for the info? Or how should this be solved?

The actual React.renderComponent is called from top level and that triggers all the subcomponents so I think I cannot force new render (and I shouldn't?).

1
  • You shouldn't have any backend calls in the rendering routine! Commented Jun 12, 2014 at 14:46

2 Answers 2

23

You need to do something like below:

var InfoPage = React.createClass({
  getInitialState: function() {
     return {info: "loading ... "};
  },
  componentDidMount: function() {
     this.getInfo();
  },
  render: function() {        
    return (
        <div>info: {this.state.info}</div>            
    );
  },
  getInfo:function(){
     $.ajax({ url:"restapi/getInfo/whatever", .... }).success(function(res){
        this.setState({info:res});
     }.bind(this));
  }
});
Sign up to request clarification or add additional context in comments.

4 Comments

How would one do this without using jQuery or jQuery.ajax()?
@ConAntonakos Why not using jQuery? If you really want to get rid of jQuery, you may want to check this site.
The use of ajax is irrelevant to the pattern that QusaiJouda is demonstrating here. You can use whatever method you want to fetch data. The point is to demonstrate the pattern of pre-populating state with temporary placeholder values.
If someone around these days, modern web dev would use fetch API (developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
18

ComponentDidMount Lifecycle Method

According to the docs, componentDidMount is the component hook you should be using to do your ajax request:

http://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount

ComponentDidMount

Invoked immediately after rendering occurs... If you want to integrate with other JavaScript frameworks, set timers using setTimeout or setInterval, or send AJAX requests, perform those operations in this method.

Example

Using your example, the code might look like this:

var InfoPage = React.createClass({
  getInitialState: function () {
    return { info: {} };
  },

  componentDidMount: function () {
    $.ajax({
      url: '/info.json',
      dataType: 'json',
      success: function(data) {
        this.setState({info: data});
      }.bind(this)
    });
  },

  render: function() {        
    return (
      <div>info: {this.state.info}</div>            
    );
  }
});

getInitialState

Above, we are using the getInitialState method to return an empty info object. This allows our component to render, while we wait for the server to return with data.

Once componentDidMount executes, it will use this.setState to replace the empty info and the server data and re-render the component.

Further reading

You can see this approach used in in the Updating state section of the React tutorial.

1 Comment

This offers a somewhat related best practice, but fails to answer the actual question. The OP wants to finish an async request BEFORE rendering is complete. What this is suggesting is to run any async method after rendering or to rerender after rendering the first time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.