【问题标题】:How to get temperature units on weather api call?如何在天气 api 调用中获取温度单位?
【发布时间】:2019-11-05 01:44:59
【问题描述】:

我正在开发 Reactjs 天气项目,该项目从特定的天气 api 获取数据。在加载项目时,我会通过 getCurrentPosition 函数获取我所在城市的温度信息。温度单位也可以通过拨动开关从摄氏度更改为华氏温度,反之亦然,这是我的主要目标。但是,如何在特定城市搜索中获取温度单位值?简而言之,我想在城市搜索中切换温度单位。

以下是供参考的文件 1. App.js(主文件)

class App extends React.Component  { 
  constructor(props) {
    super(props);

    this.state = {
      isLoading: true,
      lat: '',
      lon: '',
      city: '',
      country: '',
      humidity: '',
      temperature: '',
      wind: '',
      description: '',
      maxTemp: '',
      minTemp: '',
      precip: '',
      pressure: '',
      hourlyforecast: '',
      error: '',
      unit: 'C',
      sunrise: '',
      sunset: '',
    }
  }

  componentDidMount = async () => {

      // Tracking the location and 
      // Setting the state of latitude and longitude values
      navigator.geolocation.getCurrentPosition(async (position) => {
        this.setState({
          lat:  position.coords.latitude.toFixed(3),
          lon: position.coords.longitude.toFixed(3)
        }, () => { 
           if(this.state.lat && this.state.lon) {
            this.fetchWeather()
          } else {
            this.getWeather()
          }
        })
      },
      (error) => {
        toast.error(`${error.message}`,{
          autoClose: 3000
        })
    },
      {
        enableHighAccuracy: true,
        timeout: 50000,
        maximumAge: 1000
      })
  }


fetchWeather = () => {
  const {lat, lon} = this.state
  const unitType = (this.state.unit === 'C') ? 'M' : 'I';
  console.log('UNITTYPE', unitType)

        // Current Weather
  fetch(`${CURRENT_API}lat=${lat}&lon=${lon}&units=${unitType}&key=${API_KEY3}`)
  .then(res => res.json()).then(responseJson => {
    try {
      console.log('DATA CURRENT', responseJson)
    this.setState({
    city: responseJson.data[0].city_name,
    country: responseJson.data[0].country_code,
    temperature: responseJson.data[0].temp,
    wind: responseJson.data[0].wind_spd,
    humidity: responseJson.data[0].rh,
    pressure: responseJson.data[0].pres,
    description: responseJson.data[0].weather.description,
    isLoading: false, 
    }, () => {
      localStorage.setItem('weather', JSON.stringify(this.state))
    })
    } catch {
      toast.error('Error Code 429')
    }

  });

  // Forecast Weather - Daily
  fetch(`${FORECAST_API}lat=${lat}&lon=${lon}&units=${unitType}&days=6&key=${API_KEY3}`)
  .then(res => res.json()).then(responseJson => {
    try {
      console.log('DATA I GET', responseJson)
      this.setState({
      forecastdays: responseJson.data,
      precip: responseJson.data[0].pop,
      maxTemp: responseJson.data[0].app_max_temp,
      sunrise: responseJson.data[0].sunrise_ts,
      sunset: responseJson.data[0].sunset_ts,
      minTemp: responseJson.data[0].app_min_temp,
      isLoading: false 
      } , () => {
        localStorage.setItem('weather', JSON.stringify(this.state))
      })
    } catch {
      toast.error('Too many requests')
    }

  });


  // Forecast Weather - Hourly
  fetch(`${HOURLY_API}lat=${lat}&lon=${lon}&units=${unitType}&key=${API_KEY3}&hours=10`)
  .then(res => res.json()).then(responseJson => {
    try {
      this.setState({
        hourlyforecast: responseJson.data,
        isLoading: false
      }, () => {
        localStorage.setItem('weather', JSON.stringify(this.state))
      })

    } catch {
      toast.error('Please wait some time')
    }

  });
  }
  1. 输出切换开关值的函数
onUnitChange = (newUnit) => {
    this.setState({
        unit: newUnit
    }, this.fetchWeather, this.getWeather)
}

直到上面的代码我得到输出

现在问题来了->如何将单位值传递给getWeather函数?

  1. 根据城市输入搜索天气信息的功能
  getWeather = async (e) => {
    e.preventDefault();
    const city = e.target.elements.city.value;
    const unitType = (this.state.unit === 'C') ? 'M' : 'I';

    try {
      // 1. weatherbit current data
      const api_call4 = await fetch(`https://api.weatherbit.io/v2.0/current?` + 
      `city=${city}&units=${unitType}&key=${API_KEY3}`)
      const data4 = await api_call4.json();
      console.log('DATA CURRENT', data4)

      // 2. weatherbit forecast data
      const api_call3 = await fetch(`https://api.weatherbit.io/v2.0/forecast/daily` + 
      `?city=${city}&units=${unitType}&days=6&key=${API_KEY3}`)
      const data3 = await api_call3.json();
      console.log('DATA FORECAST', data3)

      // 3. weatherbit hourly data
      const api_call2 = await fetch(`https://api.weatherbit.io/v2.0/forecast/hourly` + 
      `?city=${city}&units=${unitType}&key=${API_KEY3}&hours=10`)
      const data2 = await api_call2.json();
      console.log('DATA HOURLY', data2)

      if(city) {
      this.setState({
        temperature: data4.data[0].temp,
        city: data4.data[0].city_name,
        country: data4.data[0].country_code,
        humidity: data4.data[0].rh,
        maxTemp: data4.data[0].app_max_temp,
        minTemp: data4.data[0].app_min_temp,
        wind: data4.data[0].wind_spd,
        description: data4.data[0].weather.description,
        pressure: data4.data[0].pres,
        error: "",
        precip: data3.data[0].pop,
        forecastdays: data3.data,
        hourlyforecast: data2.data,        
        maxTemp: data3.data[0].app_max_temp,
        minTemp: data3.data[0].app_min_temp,
        sunrise: data3.data[0].sunrise_ts,
        sunset: data3.data[0].sunset_ts,
        isLoading: false
      }, () => {
        localStorage.setItem('weather2', JSON.stringify(this.state))
      })
    } else if(city === '') {
      this.setState({
        temperature: this.state.temperature,
        city: this.state.city,
        country: this.state.country,
        humidity: this.state.humidity,
        wind: this.state.wind,
        description: this.state.description,
        pressure: this.state.pressure,
        forecastdays: this.state.forecastdays,
        hourlyforecast: this.state.hourlyforecast,
        precip: this.state.precip,
        maxTemp: this.state.maxTemp,
        minTemp: this.state.minTemp,
        error: toast.error("City cannot be empty",{
          autoClose: 3000
        })
      })

    } 
    }

    catch {
      toast.error('No Data Received', {
        autoClose: 3000
      })
    }

    localStorage.getItem('weather2')
  }

render() {
    const {isLoading, forecastdays, hourlyforecast, precip} = this.state;

    return (
      <div className="container" style={{marginTop: '3.5em'}}>
        <div className="row">

            <div className="col-sm-4 form-container">
              <Form getWeather={this.getWeather}/>
              <ToastContainer transition={Bounce} 
              className = 'toast-background'/>    
            </div>  

          {isLoading ? <Spinner/>:  

          <React.Fragment>
          <div className="col-sm-8 image-container">
          {/* Weather Card */}
          <div className="background">
          <div className="container"> 
          <div id="card" className="weather" style={sectionStyle}></div>    
          <div id="card" className="weather2" style={{background: ''}}>

                  <div className="details">
                      {/* Weather Details */}
                       <div className="content" style={{width: '125px'}}>
                        <Weather
                          temperature={this.state.temperature}
                          city={this.state.city}
                          country={this.state.country}
                          humidity={this.state.humidity}
                          description={this.state.description}
                          pressure={this.state.pressure}
                          wind={this.state.wind}
                          maxTemp={this.state.maxTemp}
                          minTemp={this.state.minTemp}
                          precip={precip}
                          tempUnit={this.state.tempUnit}
                          />

                       </div>

                      {/* Forecast Cards */}

                      <div className="content" style={{width: '360px', marginTop: '-40px'}}>

                             <div style={{display: 'table', width: '300px'}}>
                             <SunriseSunset 
                             style={{display: 'table-cell'}}
                             sunrise={this.state.sunrise} 
                             sunset={this.state.sunset}
                           />

                           <ConvertTempButton 
                             style={{display: 'table-cell'}}
                             changeUnit={this.onUnitChange}
                             onUnitChange={this.onUnitChange}
                             unit={this.state.unit}
                           />

                             </div>      
                          <DailyHourly forecastdays={forecastdays} hourlyforecast={hourlyforecast}/>   
                       </div>
                      {/* Forecast Cards Ends*/  }          
                  </div> 
              </div>
           </div>
          </div>
</div>
          {/* Video Background Ends */}
          </div>
          {/* Weather Card Ends */}

          </React.Fragment>

        }
        </div>
      </div>
    );
  }

export default App

我知道上面的代码不合适,但是,实现结果的正确方法是什么?非常感谢代码中的任何建议或更改。提前致谢

【问题讨论】:

  • 温度单位是​​您使用的特定天气 API 返回的任何内容。您使用的是哪个天气 API?
  • 只用this.state.unit?
  • 我正在使用weatherbit api
  • Pranav 你能解决问题吗?您尝试过@MaazSyedAdeeb 的建议吗?如果问题没有解决,我会发布答案。
  • 我有点困惑 this.state.unit 应该在哪里使用,根据@MaazSyedAdeeb?当我输入特定的城市,然后切换摄氏度以华氏温度时,天气信息将返回到我当前的位置

标签: javascript reactjs


【解决方案1】:

我猜这个 Weatherbit API 默认为您提供摄氏温度。因此,每次调用 api 时,您得到的结果都会以摄氏度本身为单位。您可以使用状态变量将其转换为华氏或任何其他单位,反之亦然。

例如:

state = {
  unit: 'C'
} 

handleToggle = () => {
 if(this.state.unit === 'C'){
   var temp = this.state.temp;
   //convert to Fahrenheit 
   var newtemp = //newvalue
   this.setState({ unit: 'F', temp: newtemp});
}else{
  var temp = this.state.temp;
  //convert to Celcius
  newtemp = //newvalue
  this.setState({ unit: 'C', temp: newtemp});
}
}

希望对你有帮助

【讨论】:

    【解决方案2】:

    我想念你打电话给setState 的方式。您可以通过将两个回调添加到另一个回调中,然后在 getWeatherfetchWeather 中使用 this.state.unit 来实现。喜欢

    onUnitChange = (newUnit) => {
        this.setState({
            unit: newUnit
        }, () => { this.fetchWeather(); this.getWeather(); })
    }
    

    一个有效的简化示例:

    class App extends React.Component {
      state = {
        value: 0
      };
    
      onButtonClick = () => {
        this.setState(
          ({ value }) => ({ value: ++value }),
          () => {
            this.first();
            this.second();
          }
        );
      };
    
      first = () => {
        console.log("First:", this.state.value);
      };
    
      second = () => {
        console.log("Second:", this.state.value);
      };
    
      render() {
        const { value } = this.state;
        return (
          <div>
            <div>Value: {value}</div>
            <button onClick={this.onButtonClick}>Update</button>
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    【讨论】:

    • 在上面的代码中,getWeather(e) 有 e.preventDefault() 从其他函数调用时会抛出错误
    • 是的。那是因为您期望它是一个事件处理程序以及一个可以独立调用的函数。因此,您需要管理这两种类型的调用。在这种情况下,当你独立调用它时,想办法将来自e 的任何内容作为额外参数传递。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 2017-03-25
    相关资源
    最近更新 更多