开发者问题收集

react.js 中 Openweather api 调用失败

2021-02-03
394

我想通过开放天气 API 获取天气数据。我注意到控制台中的数据没有下载,即使与 API 的连接也正确建立。通过在浏览器中输入 API 地址,将显示数据。单击获取天气按钮后,不会下载任何数据。我在代码中遇到了一个有问题的代码片段。是什么导致了此代码中的问题?

 e.preventDefault();

    const city = e.target.elements.city.value;
    const country = e.target.elements.country.value;

上述这段代码在通过 API 获取数据时会导致问题。如果我删除它,数据将通过 API 下载,不会出现任何问题,并且我会获得伦敦的当前天气。

整个 App.js

import React from "react";

import './App.css';

import 'weather-icons/css/weather-icons.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import Weather from "./components/weather.component";
import Form from "./components/form.component";


const API_KEY = "79b5009058dfaeaae8ed70533cb72a0d";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      city: undefined,
      country: undefined,
      icon: undefined,
      main: undefined,
      celsius: undefined,
      temp_max: undefined,
      temp_min: undefined,
      description: '"',
      error: false
    };

    this.weatherIcon = {
      Thunderstorm: "wi-thunderstorm",
      Drizzle: "wi-sleet",
      Rain: "wi-storm-showers",
      Snow: "wi-snow",
      Atmosphere: "wi-fog",
      Clear: "wi-day-sunny",
      Clouds: "wi-day-fog"
    };
  }

  calCelsius(temp) {
    let cell = Math.floor(temp - 273.15);
    return cell;
  }

  get_WeatherIcon(icons, rangeId){
    switch(true){
      case rangeId >= 200 && rangeId <= 232: 
        this.setState({icon: this.weatherIcon.Thunderstorm})
        break;
      case rangeId >= 300 && rangeId <= 321: 
        this.setState({icon: this.weatherIcon.Drizzle})
        break;
      case rangeId >= 500 && rangeId <= 531: 
        this.setState({icon: this.weatherIcon.Rain})
        break;
      case rangeId >= 600 && rangeId <= 622: 
        this.setState({icon: this.weatherIcon.Snow})
        break;
      case rangeId >= 701 && rangeId <= 781: 
        this.setState({icon: this.weatherIcon.Snow})
        break;
      case rangeId === 800: 
        this.setState({icon: this.weatherIcon.Clear})
        break;
      case rangeId >= 801 && rangeId <= 804: 
        this.setState({icon: this.weatherIcon.Clouds})
        break;
      default: 
        this.setState({icon: this.weatherIcon.Clouds})
    }
  }

  getWeather = async(e)=>{

    e.preventDefault();

    const city = e.target.elements.city.value;
    const country = e.target.elements.country.value;

    if(city && country) {
      const api_call = await fetch(`http://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=${API_KEY}`);
  
      const response = await api_call.json();
  
      console.log(response);
  
    this.setState({
      city: response.name,
      country: response.country,
      celsius: this.calCelsius(response.main.temp),
      temp_max: this.calCelsius(response.main.temp_max),
      temp_min: this.calCelsius(response.main.temp_min),
      description: response.weather[0].description,
    });
      this.get_WeatherIcon(this.weatherIcon, response.weather[0].id);
    } else {
      this.setState({error: true});
    }
  };

  render() {
    return (
      <div className="App">
      <Form loadweather={this.getWeather} error={this.state.error}/>
      <Weather 
        city={this.state.city} 
        country={this.state.country} 
        temp_celsius={this.state.celsius}
        temp_max={this.state.temp_max}
        temp_min={this.state.temp_min}
        description={this.state.description}
        weatherIcon={this.state.icon} 
      />
    </div>
    )
  }
}


export default App;

form.component.jsx

import React from "react";
import "./form.style.css";

const Form = props => {
    return(
    <div className="container">
        <div>{props.error ? error() : null}</div>
        <form action="">
        <div className="container">
            <div className="row">
                <div className="col-md-3 offset-md-2">
                    <input 
                        type="text" 
                        className="form-control" 
                        name="city" 
                        autoComplete="off" 
                        placeholder="City"
                    />
                </div>
                <div className="col-md-3">
                    <input 
                        type="text" 
                        className="form-control" 
                        name="country" 
                        autoComplete="off" 
                        placeholder="Country"
                    />
                </div>
                <div className="col-md-3 mt-md-0 text-md-left">
                    <button onSubmit={props.loadweather} className="btn btn-warning">Get Weather</button>
                </div>
            </div>
            </div>
        </form>
    </div>
    );
}

function error() {
    return(
    <div className="alert alert-danger mx-5" role="alert">
        Please Enter City and Country
    </div>
    )
}
export default Form;

weather.component.jsx

import React from 'react';

const Weather = (props) => {
    return(
        <div className="container">
            <div className="cards pt-4">
            <h1>{props.city}</h1>
            <h5 className="py-4">
               <i className={`wi ${props.weatherIcon} display-1`} /> 
            </h5>

            {props.temp_celcius ? (<h1 className="py-2"></h1>): null}
            <h1 className="py-2">{props.temp_celsius}&deg;</h1>

             {minmaxTemp(props.temp_min, props.temp_max)}

             <h4 className="py-3">{props.description}</h4>
            </div>
        </div>
    );
};

function minmaxTemp(min,max) {
    if(min && max) {
        return(
            <div>
                <span className="px-4">{min}&deg;</span>
                <span className="px-4">{max}&deg;</span>
            </div>          
        );
    }
}

export default Weather;
1个回答

问题似乎出在 form.component.jsx

尝试使用

<input className="btn btn-warning" type="submit" value="Get Weather" />

而不是

<button onSubmit={props.loadweather} className="btn btn-warning">Get Weather</button>

另外,使用

<form onSubmit={props.loadweather}>

以防万一,请参考此内容: https://reactjs.org/docs/forms.html

祝您编码愉快!

Akshay
2021-02-04