React + AJAX组件过度渲染

时间:2016-09-21 21:26:09

标签: javascript ajax reactjs

为了填充React组件的内容,我在方法componentWillMount的主体中使用AJAX请求,在那里我因执行请求而更改this.state。问题是render方法在请求完成之前运行,就像this.state在setState之后更改一样。此外,如果这样的组件呈现一个,也使用AJAX,则渲染调用的数量增长为2的幂。

如何在获得必要的数据后才能渲染组件?

var News = React.createClass({
    getInitialState: function () {
        return {
            news: [],
            page: 1
        };
    },

    componentWillMount: function () {
        let xmlhttp = getXmlHttp();
        xmlhttp.open("POST", "server/news.php", true);
        xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xmlhttp.onreadystatechange=() => {
            if (xmlhttp.readyState != 4) return;
            clearTimeout(timeout);
            if (xmlhttp.status == 200) {
                this.setState({
                    news: eval(xmlhttp.responseText.toString())
                });
            } else {
                handleError(xmlhttp.statusText);
            }
        };
        xmlhttp.send('page=' + this.state.page);
        var timeout = setTimeout( function(){ xmlhttp.abort(); handleError("Request time over") }, 10000);
    },

    render: function () {
        let itemList = this.state.news.map(function(item, iterator){
            return (
                <NewsItem
                    niTitle={item[0]}
                    niText={item[1]}
                    niDate={item[2]}
                    niImg={item[3]}
                    key={"ni " + iterator}
                />
            );
        });
        return (
            <div>
                {itemList}
                <PageChanger page={this.state.page}/>
            </div>
        );
    }
});

2 个答案:

答案 0 :(得分:3)

  

如何在获取组件后才能渲染组件   必要的数据?

如果您的render函数返回false,则不会呈现任何内容。 (来源:the docs。)

因此,您可以在初始状态下设置一个标志:

getInitialState: function () {
    return { page: 1, shouldRender: false };
}

然后,在render中,您可以检查该标志:

if (! this.state.shouldRender) return false;

在传递给XHR的回调中,您可以更新标志:

this.setState({
  shouldRender: true,
  news: eval(xmlhttp.responseText.toString()),
});

答案 1 :(得分:-1)

首先,将您的网络调用抽象为帮助程序,并根据需要导入到组件中。

其次,使用componentDidMount而不是componentWillMount来避免多次渲染。

例如:

import networkCall from ../helpers/networkCall 
    componentDidMount() {
        this.setState({
            emails: networkCall.news,
            emailCache: networkCall.page
        });
    },