Javascript 使用Ajax在React中打开天气数据
在给定的条件下,我尝试使用ajax将当前天气数据拉入React.js应用程序,提取给定城市的当前温度值,然后在我的组件中呈现该值 我正在处理的测试JSON数据位于以下url:Javascript 使用Ajax在React中打开天气数据,javascript,jquery,json,ajax,reactjs,Javascript,Jquery,Json,Ajax,Reactjs,在给定的条件下,我尝试使用ajax将当前天气数据拉入React.js应用程序,提取给定城市的当前温度值,然后在我的组件中呈现该值 我正在处理的测试JSON数据位于以下url: var CityGrid=React.createClass({ componentDidMount:function(){ $.ajax({ 网址:'http://api.openweathermap.org/data/2.5/weather?id=5391997', //^^这应该得到一个设置了id=5391997
var CityGrid=React.createClass({
componentDidMount:function(){
$.ajax({
网址:'http://api.openweathermap.org/data/2.5/weather?id=5391997',
//^^这应该得到一个设置了id=5391997的变量
数据类型:“json”,
成功:功能(数据){
这个.setState({temp:data.main.temp});
}.绑定(此),
错误:函数(xhr、状态、错误){
console.error(this.props.url,status,err.toString());
}.绑定(此)
});
},
getInitialState:函数(){
返回{
城市:[
{
名称:“旧金山”,
身份证号码:5391997,
temp:50,//在data
上设置state
之前,此.state.data
未定义。您可以通过在定义之前不呈现此.state.data
中的任何内容,或设置数据:{}来解决此问题
在您的getInitialState
中,这可能会有一些错误,但我认为这应该会让您非常接近
var React = require("react");
var $ = require("jquery");
var City = React.createClass({
propTypes: {
id: React.PropTypes.string.isRequired,
units: React.PropTypes.string
},
getInitialState: function () {
return {
data: {},
fetching: false
};
},
getDefaultProps: function () {
return {
units: "imperial"
};
},
render: function () {
return (
<div class="city">
{this.state.fetching ? "Downloading data..." : this.state.data.main.temp}
</div>
);
},
componentWillMount: function () {
$.ajax({
url: "http://api.openweathermap.org/data/2.5/weather?id="+this.props.id+"&units="+this.props.units,
dataType: "json",
beforeSend: function () {
this.setState({fetching: true});
},
success: function (data) {
this.setState({data: data});
},
error: function (xhr, status, err) {
console.error(xhr, status, err.toString());
},
complete: function () {
this.setState({fetching: false});
},
context: this
});
}
});
var CityGrid = React.createClass({
propTypes: {
cityIds: React.PropTypes.array.isRequired
},
renderCity: function (cityId) {
return <City id={cityId} />;
},
render: function () {
return (
<div class="city-grid">
{this.props.cityIds.map(this.renderCity)}
</div>
);
}
});
var React=require(“React”);
var$=require(“jquery”);
var City=React.createClass({
道具类型:{
id:React.PropTypes.string.isRequired,
单位:React.PropTypes.string
},
getInitialState:函数(){
返回{
数据:{},
抓取:假
};
},
getDefaultProps:函数(){
返回{
单位:“帝国”
};
},
渲染:函数(){
返回(
{this.state.fetching?“下载数据…”:this.state.data.main.temp}
);
},
componentWillMount:函数(){
$.ajax({
url:“http://api.openweathermap.org/data/2.5/weather?id=“+this.props.id+”&units=“+this.props.units,
数据类型:“json”,
beforeSend:函数(){
this.setState({fetching:true});
},
成功:功能(数据){
this.setState({data:data});
},
错误:函数(xhr、状态、错误){
console.error(xhr,status,err.toString());
},
完成:函数(){
this.setState({fetching:false});
},
背景:这
});
}
});
var CityGrid=React.createClass({
道具类型:{
CityId:React.PropTypes.array.isRequired
},
renderCity:函数(cityId){
返回;
},
渲染:函数(){
返回(
{this.props.cityIds.map(this.renderCity)}
);
}
});
话虽如此,但这不是正确的解决方案。ajax调用应该移到组件之外(您是否研究过Flux或其他一些库,这些库将为您提供模型或存储的概念?),即返回的“数据”然后应该以某种方式转换/规范化为平面结构,然后作为道具传递给城市组件(并且只传递有意义/您关心的道具)。这样,城市组件可以不知道其数据来自何处。从理论上讲,您应该能够使用其他来源、多个来源、虚拟数据等的数据渲染城市。但我不打算为您编写所有代码;)您能发布该console.log的结果吗?您在哪一行得到错误?当然,在我的渲染函数中是console.log(this.state.data.main.temp),我的控制台显示“Uncaught TypeError:无法读取未定义的属性'main'”可能是因为您没有在initialState中设置数据。在ajax返回之前,this.state.data是未定义的。您是否尝试过我发布的代码?因为我只是在JSFIDLE中运行了它,它工作得很好。好的,我已经实例化了
数据:{}
,在getInitialState
函数中的my cities数组上方。现在,渲染函数中的my console.log将仅限于this.state.data.main
。当我尝试记录this.state.data.main.temp
时,我会得到相同的“未捕获类型错误:无法读取未定义的属性'temp'error.right,因为此时还未定义this.state.data.main
。因此您可以将getInitialState
设置为data:{main:{temp:0}}
或检查它是否已定义:if(this.state.data.main){console.log(this.state.data.main.temp);}
但是从ajax调用中,我会以一种有意义的方式设置状态,而不一定是如何返回的。也就是说,只需setState({temp:data.main.temp})
,然后只渲染this.state.temp
。谢谢,这是一个很大的进步。但是,我似乎不能将渲染函数中的值用作temp={this.state.temp}
,这可能是因为我映射{this.state.cities.map(函数(city,I){……}
对于每个城市。我仍然感觉很困惑。好吧,退一步,组件应该呈现什么?12个不同城市的温度?如果是这样,我只需循环遍历每个城市,并将其温度添加到状态。像这样,感谢您的详细回复!我想知道,城市ID如何在url中使用?我看不到cityIds数组(看起来像var cityIds=[5391997,5809844,4853799,…])
的位置。另外,我的12个城市对象中的每一个都有6个属性,看起来像这样:cities:[{名称,温度,天气图标,UTCOffset,地址,url,电话,callphone}]
。我正在试图找到一种方法,使您的代码在我的代码中工作。您可以向CityGrid组件传递一个CityID数组。CityGrid呈现每个城市,并向城市传递一个id。城市使用该id进行ajax调用。一旦您成功,您可以添加额外的id
var React = require("react");
var $ = require("jquery");
var City = React.createClass({
propTypes: {
id: React.PropTypes.string.isRequired,
units: React.PropTypes.string
},
getInitialState: function () {
return {
data: {},
fetching: false
};
},
getDefaultProps: function () {
return {
units: "imperial"
};
},
render: function () {
return (
<div class="city">
{this.state.fetching ? "Downloading data..." : this.state.data.main.temp}
</div>
);
},
componentWillMount: function () {
$.ajax({
url: "http://api.openweathermap.org/data/2.5/weather?id="+this.props.id+"&units="+this.props.units,
dataType: "json",
beforeSend: function () {
this.setState({fetching: true});
},
success: function (data) {
this.setState({data: data});
},
error: function (xhr, status, err) {
console.error(xhr, status, err.toString());
},
complete: function () {
this.setState({fetching: false});
},
context: this
});
}
});
var CityGrid = React.createClass({
propTypes: {
cityIds: React.PropTypes.array.isRequired
},
renderCity: function (cityId) {
return <City id={cityId} />;
},
render: function () {
return (
<div class="city-grid">
{this.props.cityIds.map(this.renderCity)}
</div>
);
}
});