2016-09-24 2 views
0

私はReactで天気ウィジェットを作ろうとしています。React:レンダリング前に要求されたデータが利用可能であることを確認する方法?

私はOpenWeatherMapから取得する使用データ: http://openweathermap.org/api

私の問題は、レンダリング機能を一度に呼ばれているということであった(またはです)。しかし、OpenWeatherMap APIからの要求されたデータはまだ利用できません。したがって、(まだ)定義されていない小道具にアクセスするので、インタプリタはエラーを投げます。

私は描画の機能のreturn文を置くことによって回避策を発見したのif-else:

var React = require('react'); 
 
var DayInfos = require('./DayInfos.jsx'); 
 
var MainInfoPanel = require('./MainInfoPanel.jsx'); 
 

 
var WeatherApp = React.createClass({ 
 
    getInitialState: function() { 
 
    return {  
 
     data: null 
 
    } 
 
    }, 
 
    componentWillMount: function() { // Call before the initial rendering 
 
    var apiData = new Promise(function(resolve, reject) { 
 
     var request = new XMLHttpRequest(); 
 

 
     request.onreadystatechange = function() { 
 
     if (request.readyState === 4) { 
 
      if (request.status === 200) { 
 
      resolve(request.responseText); 
 
      } else { 
 
      reject('HTTP request on openweathermap has failed.'); 
 
      } 
 
     } 
 
     } 
 

 
     request.open('get', 'http://api.openweathermap.org/data/2.5/forecast?q=London,us&mode=json&appid=efcd313fa7a139f2fb20de306648eb8d'); 
 
     request.send(); 
 
    }); 
 

 
    apiData.then(function(weatherData) { 
 
     this.setState({ 
 
     data: JSON.parse(weatherData) 
 
     }); 
 
    }.bind(this), function(message) { 
 
     console.log(message); 
 
    }); 
 
    }, 
 
    render: function() { 
 
    if (this.state.data) { // Make sure the data is available. 
 
     return (
 
     <div className="weather-app" > 
 
      <MainInfoPanel city={ this.state.data.city } today={ this.state.data.list[0] } /> 
 
      <DayInfos /> 
 
      <DayInfos /> 
 
      <DayInfos /> 
 
      <DayInfos /> 
 
     </div> 
 
    ); 
 
    } else { 
 
     return null; 
 
    } 
 
    } 
 
}); 
 

 
module.exports = WeatherApp;

私が動作するようになりましたが、私は私が扱うのかはわかりません適切な方法で発行してください。

実際に私は、使用された機能のコンポーネントであるWillMount(https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount)が問題を処理すると思っていました。しかし、明らかに要求をトリガするだけです。残りは、データが到着するのを待つことなく、さらに実行されます。より多くの経験を積んリアクト - 開発者に

は、したがって、私の質問:

要求されたデータが利用可能になるまでどのように1は、初期のレンダリングを遅らせることができますか?

または:

ためのデータを欠いているのクラッシュの適用を回避するための適切な戦略とは何ですか?

答えて

2

私は通常のウィジェットがロードであることを示すためにスピナーを使用します。

render() { 
    return this.state.loading ? (
     <div className="spinner"> 
     <Spinner /> 
     </div> 
    ) : this.renderView(); 
    } 

renderView()state.loadingがfalseの場合、実際のレンダリングを行います。 state.loadingがtrueの場合、スピナーが表示されます。

componentWillMountでは、API呼び出しを行う前にloadingをtrueに設定しました。

componentWillMount() { 
    this.setState({loading: true}); 
    ajaxCall().then(responses => { 
     // process response 
     this.setState({loading: false}); 
    }); 
    } 
3

フラグ条件を最初にfalseに設定し、データが到着したらtrueに設定する必要があります。

var React = require('react'); 
var DayInfos = require('./DayInfos.jsx'); 
var MainInfoPanel = require('./MainInfoPanel.jsx'); 

var WeatherApp = React.createClass({ 
    getInitialState: function() { 
    return {  
     data: null, 
     flag:false, //add flag 
    } 
    }, 
    componentWillMount: function() { // Call before the initial rendering 
    var apiData = new Promise(function(resolve, reject) { 
     var request = new XMLHttpRequest(); 

     request.onreadystatechange = function() { 
     if (request.readyState === 4) { 
      if (request.status === 200) { 
      resolve(request.responseText); 
      } else { 
      reject('HTTP request on openweathermap has failed.'); 
      } 
     } 
     } 

     request.open('get', 'http://api.openweathermap.org/data/2.5/forecast?q=London,us&mode=json&appid=efcd313fa7a139f2fb20de306648eb8d'); 
     request.send(); 
    }); 

    apiData.then(function(weatherData) { 
     this.setState({ 
     data: JSON.parse(weatherData), 
     flag:true // update state 
     }); 
    }.bind(this), function(message) { 
     console.log(message); 
    }); 
    }, 
    render: function() { 
    return flag ? 
     (
     <div className="weather-app" > 
      <MainInfoPanel city={ this.state.data.city } today={ this.state.data.list[0] } /> 
      <DayInfos /> 
      <DayInfos /> 
      <DayInfos /> 
      <DayInfos /> 
     </div> 
    ) 
    : 
     null; 
    } 
    } 
}); 

module.exports = WeatherApp 

別の変数を使用したくない場合は、data.lengthプロパティを使用しても追跡できます。

しかし、ここであなたが次にあなたのレンダリングが

render: function() { 
     return data.length > 0 ? 
      (
      <div className="weather-app" > 
       <MainInfoPanel city={ this.state.data.city } today={ this.state.data.list[0] } /> 
       <DayInfos /> 
       <DayInfos /> 
       <DayInfos /> 
       <DayInfos /> 
      </div> 
     ) 
     : 
      null; 
     } 
     } 
    }); 
+0

ありがとうございます。あなたは私をたくさん助けました。 1つの答えしか受け入れることはできませんが、両方が役に立ちました。だから私は少なくとも2つのupvotesを受け取りました。 –

1

より便利な(しかし、おそらくあまり目立たない)方法のようになります。[]またはデータ= {} =データ、データに型配列やオブジェクトを割り当てる必要があります行うには、次のようになります。

render: function() { 
    return (
    this.state.data && 
     <div className="weather-app"> 
     <MainInfoPanel city={this.state.data.city} today={...} /> 
     <DayInfos /> 
     <DayInfos /> 
     <DayInfos /> 
     <DayInfos /> 
     </div> 
); 
} 

this.state.dataがtruthyある場合<div>...</div>が返されます、と私は三項演算子と: null;を記述することで保存します。

+0

クール。どうもありがとう。 –

関連する問題