React - 在ComponentWillReceiveProps中加载存储的数据然后加载API数据

时间:2017-03-24 04:04:17

标签: javascript reactjs asynchronous

我有一个必须基于新道具发出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完成之后,这似乎完全不符合我的要点。

我可以使用更好的策略来实现这个目标吗?

谢谢!

2 个答案:

答案 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也可能有所帮助