使用Ajax在{React}中打开天气数据

时间:2015-10-01 22:47:05

标签: javascript jquery json ajax reactjs

鉴于Open Weather Map current weather data API,我尝试使用ajax将当前天气数据导入我的React.js应用,提取给定城市的当前临时值,然后在我的组件中渲染该值

我正在使用的测试JSON数据位于以下网址: http://api.openweathermap.org/data/2.5/weather?id=5391997&units=imperial

var CityGrid = React.createClass({
  componentDidMount: function() {
    $.ajax({
      url: 'http://api.openweathermap.org/data/2.5/weather?id=5391997', 
      // ^^ this should get a variable where id=5391997 is set
      dataType: 'json',  
      success: function(data) {
          this.setState({temp: data.main.temp});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  getInitialState:function(){
    return{
      cities:[
        { 
          name: "San Francisco",
          id: 5391997,
          temp: 50,  // << this should receive value from ajax call
          UTCOffset:-7,
          address: 999 Nathan Lane,
          phone: 555-5555
        },
        // 12 more city objects in this array, removed for brevity
    ]}
},
render: function() {
    console.log(this.state.temp); // << this returns the right temp
    // for San Francisco, because I hardcoded the value into the url
    return(
        <div className="city-grid">
        {this.state.cities.map(function(city,i){
          return(
            <CityRow key={i} name={city.name} temp={city.temp}
            UTCOffset={city.UTCOffset} address={city.address} 
            phone={city.phone}/>
          );
        })}
      </div>
    );
  }
});

module.exports = CityGrid;

我的问题:

  1. 如何提取临时值?在我的渲染函数中,console.log返回JSON对象,这意味着数据已绑定并可在我的渲染函数中访问。但是,当我试图获得温度时,我希望温度类似于this.state.data.main.temp,我得到的错误是数据未定义。&#34;然后,我希望能够在id: 5391997,的城市对象中为12个城市中的每个城市设置此值。
  2. UPDATE ^^这已经解决了:@dkurbz建议在我的ajax成功方法中将状态设置为temp对我来说很好。

    1. 我也面临着如何为每个城市设置唯一网址的挑战。在我的ajax调用中,有id=5391997,我想从城市对象中获取并将我的ajax网址更改为&#39; baseURl&#39; + this.props.id +&#39;&amp; units = imperial&#39;。我完全不知道如何做到这一点。
    2. 更新 ^^这是我目前卡住的地方。

2 个答案:

答案 0 :(得分:2)

这可能会有一些错误,但我认为它应该让你非常接近。

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>
        );
    }
});

有人说......这不是正确的解决方案。应该将ajax调用移到组件之外(你看过Flux,还是其他一些可以给你模型或商店概念的库?),返回的&#34;数据&#34;然后应该以某种方式将其转换/标准化为平面结构,然后作为道具传递给City组件(并且只传递有意义的道具/您关心的道具)。这样,City组件可以不知道其数据来自何处。从理论上讲,你应该能够使用来自其他来源,多个来源,虚拟数据等的一些数据来呈现一个城市。但是我不会去为你编写所有这些数据;)

答案 1 :(得分:1)

setState data this.state.data之前,this.state.data未定义。您可以通过从data: {}呈现任何内容直到定义任何内容来解决此问题,或者在getInitialState中设置{{1}}。