Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactjs async rendering of components

I want to render my component after my ajax request is done.

Below you can see my code

var CategoriesSetup = React.createClass({      render: function(){         var rows = [];         $.get('http://foobar.io/api/v1/listings/categories/').done(function (data) {             $.each(data, function(index, element){                 rows.push(<OptionRow obj={element} />);             });            return (<Input type='select'>{rows}</Input>)          })      } }); 

But i get the error below because i am returning render inside the done method of my ajax request.

Uncaught Error: Invariant Violation: CategoriesSetup.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

Is there a way to wait for my ajax request to end before start rendering?

like image 807
tuna Avatar asked Nov 28 '14 16:11

tuna


People also ask

Can components be async React?

The mental model of React Async is component-first. Rather than loading data high up in your application and passing it down to a component for display, you perform the data loading at the component level. Such a component is called an async component.

Can async React to render?

With Suspense, you have the ability to suspend component rendering while async data is being loaded. You can pause any state update until the data is ready, and you can add async loading to any component deep in the tree without plumbing all the props and state through your app and hoisting the logic.

Does React re render entire component?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.


2 Answers

There are two ways to handle this, and which you choose depends on which component should own the data and the loading state.

  1. Move the Ajax request into the parent and conditionally render the component:

    var Parent = React.createClass({   getInitialState: function() {     return { data: null };   },    componentDidMount: function() {     $.get('http://foobar.io/api/v1/listings/categories/').done(function(data) {       this.setState({data: data});     }.bind(this));   },    render: function() {     if (this.state.data) {       return <CategoriesSetup data={this.state.data} />;     }      return <div>Loading...</div>;   } }); 
  2. Keep the Ajax request in the component and render something else conditionally while it's loading:

    var CategoriesSetup = React.createClass({   getInitialState: function() {     return { data: null };   },    componentDidMount: function() {     $.get('http://foobar.io/api/v1/listings/categories/').done(function(data) {       this.setState({data: data});     }.bind(this));   },    render: function() {     if (this.state.data) {       return <Input type="select">{this.state.data.map(this.renderRow)}</Input>;     }      return <div>Loading...</div>;   },    renderRow: function(row) {     return <OptionRow obj={row} />;   } }); 
like image 114
Michelle Tilley Avatar answered Sep 19 '22 21:09

Michelle Tilley


The basic example of async rendering of components is below:

import React                from 'react'; import ReactDOM             from 'react-dom';         import PropTypes            from 'prop-types';  export default class YourComponent extends React.PureComponent {     constructor(props){         super(props);         this.state = {             data: null         }            }      componentDidMount(){         const data = {                 optPost: 'userToStat01',                 message: 'We make a research of fetch'             };         const endpoint = 'http://example.com/api/phpGetPost.php';                const setState = this.setState.bind(this);               fetch(endpoint, {             method: 'POST',             body: JSON.stringify(data)         })         .then((resp) => resp.json())         .then(function(response) {             setState({data: response.message});         });     }      render(){         return (<div>             {this.state.data === null ?                  <div>Loading</div>             :                 <div>{this.state.data}</div>             }         </div>);     } } 
like image 41
Roman Avatar answered Sep 20 '22 21:09

Roman