我有一个组件,它在props中获取一些数据,并向他们发出ajax请求。
var ItemList = React.createClass({
propTypes: {
filters: React.PropTypes.object.isRequired,
},
getInitialState: function() {
return {items: []};
},
componentDidMount: function() {
this.ajaxFetchItems(this.props.filters);
},
componentWillReceiveProps: function(nextProps) {
this.ajaxFetchItems(nextProps.filters);
},
ajaxFetchItems: function(filter) {
....
this.setState({items: data});
}
}
问题是道具几乎立即被更改,有时componentDidMount
中的ajax调用比componentWillReceiveProps
中的ajax稍慢,所以初始状态是在第一次更新后写的。< / p>
如何避免缓慢的componentDidMount覆盖快速componentWillReceiveProps?
有更好的方法来处理下载数据的反应组件的生命周期吗?
答案 0 :(得分:3)
您可以为处理的最新更新设置状态时间戳。 并以某种方式确保原始Ajax请求的时间戳包含在Ajax结果中。
添加shouldComponentUpdate()
以检查收到的结果是否具有晚于状态时间戳的时间戳。如果不是:返回false,您的组件将忽略结果。
顺便说一句:根据定义,componentDidMount
和componentWillReceiveProps
只能按此顺序运行。我怀疑你的第一个Ajax调用需要很长时间才能返回结果,而你的第二个调用很快。因此,您以错误的顺序返回Ajax结果。
(不是因为反应功能慢)。
更新: 使用shouldComponentUpdate是处理这种情况的反应方式:它的目的是允许比较新状态和旧状态,并基于该比较,而不是重新渲染。
问题(很可能)是由ajax响应进入的顺序生成的:
因此,更通用的问题/解决方案将用于&#34;如何处理以错误顺序返回的ajax响应&#34;。
时间戳(在shouldComponentUpdate中)是一种方法。
另一种选择(描述为here)是使第二个请求(在componentWillReceiveProps中)中止第一个ajax请求。
<强>重温:强> 在进一步考虑之后(componentDidMount和componentWillReceiveProps中的调用感觉不对),一种更通用的反应方式来接近你的组件可能如下:
您的组件的工作基本上是:
所以它有2个输入:
且只有1个输出=列表(可能为空)。
巷道:
使用react设置它可能看起来像这样:
getInitialState() {
this.fetchAjax(this.props.filter); // initiate first ajax call here
return { list : [] }; // used to maybe display "loading.." message
}
componentWillReceiveProps(nextProps) {
this.fetchAjax(nextProps.filter); // send off ajax call to get new list with new filter
}
shouldComponentUpdate(nextProps, nextState) {
return (this.state.list != nextState.list); // only update component if there is a new list
// so when new props (filter) comes in there is NO rerender
}
render() {
createChildrenWith(this.state.list);
}
fetchAjax(filter) {
killOutStandingRequests(); // some procedure to kill old ajax requests
getListAsync…
request: filter // request new list with new filter
responseHandler: this.handleResponse // add responseHandler
}
responseHandler(data) {
this.setState({ list : data }); // put the new list in state, triggering render
}
状态中的原始时间戳将解决上面发布的问题,但我认为我将共享修订后的反应组件作为奖励...