React-приложение Прогноз погоды



Приложение, которое показывает прогноз погоды для определённых населённых пунктов.

1. Регистрируемся здесь https://openweathermap.org/forecast5
На почту приходит API key

2. Создаём приложение -weather
Для этого выполняем команду
create-react-app weather

3. Создаём компонент WeatherDisplay

Пока что он отображает произвольный текст

class WeatherDisplay extends Component {
  render() {
    return (
      <h1>Displaying some Weather!</h1>
    );
  }
}

4. Изменяем компонент App, чтобы отобразить  WeatherDisplay:

class App extends Component {
  render() {
    return (
      <div className="App">
        <WeatherDisplay name={"12345"} />
      </div>
    );
  }
}

name={"12345"} это props - свойство компонента WeatherDisplay, которое из компонента App можно передать в WeatherDisplay

5. В начале файла App добавляем список городов, для которых будем отображать погоду

const PLACES = ["London", "Moscow", "Kiev", "Minsk"];

6. При помощи метода map создадим тег button для каждого города

return (
  <div className="App">
    <WeatherDisplay name={"12345"} />
    {PLACES.map((place, index) => (
      <button
        key={index}
        onClick={() => {
          console.log('Clicked index '+index);
        }}
      >
          {place.name}
      </button>
    ))}
  </div>
);

По клику по кнопке в консоль выводится индекс каждого города в списке.

7. Нам нужно хранить в App и передавать в WeatherDisplay название города, по которому кликнули. Для этого используем state

state = {
      activePlace: 0,
    };

Здесь 0 это позиция города в массиве, то есть город по умолчанию - London

8. Изменим код функции onClick, чтобы при клике по кнопке менялось значение state

        {PLACES.map((place, index) => (
          <button
            key={index}
            onClick={() => {
              this.setState({ activePlace: index });
            }}
          >
              {place}
          </button>
        ))}

9. В компонент WeatherDisplay добавим название города

<WeatherDisplay
  key={activePlace}
  name={PLACES[activePlace]} />

10. Код компонента App

import React, {Component} from 'react';
import './App.css';
import WeatherDisplay from './components/WeatherDisplay/WeatherDisplay';

const PLACES = ["London", "Moscow", "Kiev", "Minsk"];

export default class App extends Component {
  state = {
    activePlace: 0,
  };

  render() {
    const activePlace = this.state.activePlace;
    return (
      <div className="App">       
     
        {PLACES.map((place, index) => (
          <button
            key={index}
            onClick={() => {
              this.setState({ activePlace: index });
            }} >
              {place}
          </button>
        ))}

        <WeatherDisplay
          key={activePlace}
          name={PLACES[activePlace]} />
      </div>
    );
  }

11. Переходим к компоненту WeatherDisplay

Установим для него state 

  state = {
    weatherData: null
  };

То есть пока мы ничего не знаем о погоде. Но хотим узнать. Как это сделать

12. Для получения данных о погоде используем полученный на первом шаге API key

Вот по такой ссылке https://api.openweathermap.org/data/2.5/weather?q=London&appid=b1b35bba8b434a28a0be2a3e1071ae5b нам откроются данные о погоде в Лондоне
Здесь 
London - название города, 
b1b35bba8b434a28a0be2a3e1071ae5b - API key

13. Пишем функцию

  componentDidMount() {
    const name = this.props.name;
    const URL = "https://api.openweathermap.org/data/2.5/weather?q=" +
      name +
      "&appid=b1b35bba8b434a28a0be2a3e1071ae5b";
    fetch(URL).then(res => res.json()).then(json => {
      this.setState({ weatherData: json });
    });
  }

Краткое содержание кода функции
  • Когда компонент WeatherDisplay будет создан - componentDidMount() 
  • Название города мы возьмём из props, который передали в App 
const name = this.props.name;
  • Затем используя это название сгенерируем ссылку
const URL = "https://api.openweathermap.org/data/2.5/weather?q=" + name +    "&appid=b1b35bba8b434a28a0be2a3e1071ae5b";
  • И обработаем данную ссылку асинхронно, чтобы получить данные о погоде
fetch(URL).then(res => res.json()).then(json => {
      this.setState({ weatherData: json });
    });

Результатом выполнения данной функции будет помещение в state данных  weatherData: json

14. Рассмотрим содержимое  render компонента WeatherDisplay

  • weatherData равно текущему состоянию state
    const weatherData = this.state.weatherData;
  • Изначально оно было определено нами как null. и если данные не пришли, пишем Loading - ждём данные
    if (!weatherData) return <div>Loading</div>;
  • генерируем ссылку на иконку, которую будем показывать возле названия города
    const weather = weatherData.weather[0];
    const iconUrl = "http://openweathermap.org/img/w/" + weather.icon + ".png";

15. Выводим данные о погоде

      <div>
        <h1>
          {weather.main} in {weatherData.name}
          <img src={iconUrl} alt={weatherData.description} />
        </h1>
        <p>Current: {(weatherData.main.temp - 273.15).toFixed(2)}°С</p>
        <p>High: {(weatherData.main.temp_max - 273.15).toFixed(2)}°С</p>
        <p>Low: {(weatherData.main.temp_min - 273.15).toFixed(2)}°С</p>
        <p>Wind Speed: {weatherData.wind.speed} mi/hr</p>
      </div>

Выражение (weatherData.main.temp - 273.15).toFixed(2) понадобилось чтобы перевести данные из градусов Кельвина в градусы Цельсия и округлить полученный результат до двух знаков после запятой

16. Код компонента WeatherDisplay

import React, {Component} from 'react';

export default class WeatherDisplay extends Component {
  state = {
    weatherData: null
  };
  
  componentDidMount() {
    const name = this.props.name;
    const URL = "https://api.openweathermap.org/data/2.5/weather?q=" +
      name +
      "&appid=b1b35bba8b434a28a0be2a3e1071ae5b";
    fetch(URL).then(res => res.json()).then(json => {
      this.setState({ weatherData: json });
    });
  }
  
  
  render() {
    const weatherData = this.state.weatherData;
    if (!weatherData) return <div>Loading</div>;
    const weather = weatherData.weather[0];
    const iconUrl = "http://openweathermap.org/img/w/" + weather.icon + ".png";
    return (
      <div>
        <h1>
          {weather.main} in {weatherData.name}
          <img src={iconUrl} alt={weatherData.description} />
        </h1>
        <p>Current: {(weatherData.main.temp - 273.15).toFixed(2)}°С</p>
        <p>High: {(weatherData.main.temp_max - 273.15).toFixed(2)}°С</p>
        <p>Low: {(weatherData.main.temp_min - 273.15).toFixed(2)}°С</p>
        <p>Wind Speed: {weatherData.wind.speed} mi/hr</p>
      </div>
    );
  }
}