我试图用React创建一个天气小部件。
我从OpenWeatherMap获得的数据: http://openweathermap.org/api
我的问题是(或者是)一次调用render函数。但是,OpenWeatherMap API提供的请求数据还不可用。因此,解释器会抛出错误,因为访问了尚未定义的道具。
我找到了一个解决方法,将render函数的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;
&#13;
我现在工作,但我不确定我是否以正确的方式处理这个问题。
实际上我认为使用过的函数componentWillMount(https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount)会解决这个问题。但显然它只会触发请求。其余的进一步运行而不等待数据到达。
因此我向更有经验的React开发人员提问:
在请求的数据可用之前,如何延迟初始渲染?
或者:
由于缺少数据而避免应用程序崩溃的正确策略是什么?
答案 0 :(得分: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属性进行跟踪。
但是在这里你需要为数据分配一个数组Array或Object,data = []或data = {}。然后你的渲染就像
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;
}
}
});
答案 1 :(得分:2)
我通常使用微调器来指示小部件正在加载:
resultTags
当state.loading为false时,renderView()执行实际渲染。当state.loading为true时,将显示一个微调器。
在componentWillMount中,我在进行API调用之前将loading设置为true。
render() {
return this.state.loading ? (
<div className="spinner">
<Spinner />
</div>
) : this.renderView();
}
答案 2 :(得分:1)
更方便(但可以说不太明显)的方法是:
render: function() {
return (
this.state.data &&
<div className="weather-app">
<MainInfoPanel city={this.state.data.city} today={...} />
<DayInfos />
<DayInfos />
<DayInfos />
<DayInfos />
</div>
);
}
<div>...</div>
如果this.state.data
真实,将会返回: null;
,我将不得不编写一个三元运算符并'12'
。