React + AJAX组件过度渲染

React + AJAX component over-rendering

本文关键字:组件 AJAX React      更新时间:2023-09-26

为了填充React组件的内容,我在方法componentWillMount的主体中使用AJAX请求,我在这里更改了这一点。状态作为执行请求的结果。问题是呈现方法在请求完成之前运行,就像在this之后一样。通过setState改变状态。此外,如果这样的组件呈现一个,也使用AJAX,那么呈现调用的数量将以两倍的幂增长。

如何使组件只在获得必要的数据后才呈现?

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

如何使组件呈现只有在获得必要的数据?

如果您的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()),
});

首先,将您的网络调用抽象为一个helper,并根据需要导入到组件中。

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

例如:

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