ReactJS组件的异步渲染


82

我想在我的ajax请求完成后呈现我的组件。

在下面您可以看到我的代码

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>)

        })

    }
});

但是我收到下面的错误,因为我正在ajax请求的done方法内返回render。

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

有没有一种方法可以等待我的ajax请求结束再开始渲染?


3
同样,小的nitpick却在render()例程中进行数据检索并不是一个好主意。保留render()来渲染并提取其余部分。另外,您可能只想一次获取该数据,而不是每次渲染组件时都获取。
Phil Cooper

Answers:


131

有两种处理方法,您可以选择哪种方法取决于应该拥有数据和加载状态的组件。

  1. 将Ajax请求移至父级并有条件地渲染该组件:

    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. 将Ajax请求保留在组件中,并在加载时有条件地渲染其他内容:

    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} />;
      }
    });
    

6
我在2017年偶然发现了这个答案,这两个最佳解决方案是否仍然是最佳使用方式?

@Dan React基于props和state渲染UI,因此核心概念将保持不变-进行Ajax请求,设置某些状态并重新渲染某些内容。但是,诸如高阶组件之类的模式已变得越来越流行,说明了人们如何抽象化复杂性。
Michelle Tilley

1
if (this.state.data)应该是if (this.state && this.state.data)因为有时状态可以为null。
Timo

@Timo Hm,在什么情况下会this.statenull
米歇尔·蒂里

6
@Timo初始化构造函数中的状态
路易·路易斯

8

组件异步呈现的基本示例如下:

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>);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.