我有一个必须基于新道具发出HTTP请求的组件。目前它需要一段时间来实际更新,因此我们已经实施了一个本地商店,我们希望用它来显示过去请求中的数据,然后在实际到达后显示HTTP结果。< / p>
我遇到了这个策略的问题:
componentWillRecieveProps(nextProps){
this.setState({data:this.getDataFromLocalStore(nextProps.dataToGet)});
this.setState({data:this.makeHttpRequest(nextProps.dataToGet)});
//triggers single render, only after request gets back
}
我认为发生的事情是,每个生命周期方法的所有setstates都会捆绑反应,所以在请求实际返回之前它不会触发渲染。
我的下一个策略是:
componentWillRecieveProps(nextProps){
this.setState({data:this.getDataFromLocalStore(nextProps.dataToGet)});
this.go=true;
}
componentDidUpdate(){
if(this.go){
this.setState({data:this.makeHttpRequest(this.props.dataToGet)});
}
this.go=false;
}
//triggers two renders, but only draws 2nd, after request gets back
这一个应该工作,它实际上是立即使用localstore数据调用render,然后在请求返回请求数据时再次调用它,但是第一个渲染实际上并没有向屏幕绘制任何内容! / p>
看起来似乎等待绘制真正的dom,直到componentDidUpdate完成之后,这似乎完全不符合我的要点。
我可以使用更好的策略来实现这个目标吗?
谢谢!
答案 0 :(得分:1)
一种策略可能是使用fetch加载数据,并在使用promises加载数据时调用setState。
componentWillRecieveProps(nextProps){
this.loadData(nextProps)
}
loadData(nextProps){
// Create a request based on nextProps
fetch(request)
.then(response => response.json())
.then(json => this.setState({updatedValue: json.value})
}
答案 1 :(得分:0)
我一直使用模式(假设你的request
函数支持promises)
const defaultData = { /* whatever */ }
let YourComponent = React.createClass({
componentWillRecieveProps: function(nextProps) {
const that = this
const cachedData = this.getDataFromLocalStore(nextProps)
that.setState({
theData: { loading: true, data: cachedData }
})
request(nextProps)
.then(function(res) {
that.setState({
theData: { loaded: true, data: res }
})
})
.catch(function() {
that.setState({
theData: { laodingFailed: true }
})
})
},
getInitialState: function() {
return {
theData: { loading: true, data: defaultData }
};
},
render: function() {
const theData = this.state.theData
if(theData.loading) { return (<div>loading</div>) } // you can display the cached data here
if(theData.loadingFailed) { return (<div>error</div>) }
if(!theData.loaded) { throw new Error("Oups") }
return <div>{ theData.data }</div>
}
)}
有关组件生命周期的更多信息here
顺便说一句,您可能会考虑使用集中式redux状态而不是组件状态。
另外我的猜测是你的例子因为这一行而无效:
this.setState({data:this.makeHttpRequest(this.props.dataToGet)});
makeHttpRequest
很可能是异步的,并返回undefined
。换句话说,您将data
设置为undefined
并且永远无法获得请求的结果......
编辑:关于firebase
看起来你正在使用firebase。如果您使用on
函数使用它,则makeHttpRequest
必须如下所示:
function(makeHttpRequest) {
return new Promise(function(resolve, reject) {
firebaseRef.on('value', function(data) {
resolve(data)
})
})
}
此other question也可能有所帮助