Electron+React+Typescriptでお天気アプリを作る

[Electron+React+Typescriptの開発環境を作る]()の続編として、[OpenWeatherMap](https://openweathermap.org/)を使って簡単なお天気アプリを作成しようと思います。

# API Key取得まで
API Key取得までは[無料天気予報APIのOpenWeatherMapを使ってみる](https://qiita.com/nownabe/items/aeac1ce0977be963a740)を参考にしてください。


# お天気アプリ作成
今回作るアプリは下記のWebアプリです。
![default](https://user-images.githubusercontent.com/33411216/52033731-5935c280-2569-11e9-9dd5-43bcc9a203db.gif)

コードはhttps://github.com/butachin/Weather-App に書いてあります。

## Componentの作成
今回は上記でお見せしたような１つ１つのデータに対してカード(WeatherCard)を作成し、それをリスト(WeatherCardList)として表示するアプリを作成します。[redux](https://github.com/reduxjs/redux)は使わないので手をつけやすいと思います。

### WeatherCard
<img width="800" alt="スクリーンショット 2019-03-11 17.47.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/268178/34b4157a-b4d7-5384-002c-9f00f1412838.png">
[Postman](https://www.getpostman.com/)でAPIを叩くと下記のような画面が現われるので、ここで基本をhttp://api.openweathermap.org//data/2.5 として調べたい市と自分のAPIKeyを設定する。そうするとデータが返ってくるのでそれを今回のモデルとして反映する。

```src/components/WeatharCard/WeatherCardProps.ts
export interface IWeatherCard {
    dt: number;
    main: {
      temp: number;
      temp_min: number;
      temp_max: number;
      pressure: number;
      sea_level: number;
      grnd_level: number;
      humidity: number;
      temp_kf: number;
    };
    weather: [
      {
        id: number;
        main: string;
        description: string;
        icon: string;
      }
    ];
    clouds: {
      all: number;
    };
    wind: {
      speed: number;
      deg: number;
    };
    sys?: {
      pod: string;
    };
    dt_txt: string;
  }
```
interfaceとしてモデルを定義する。

```src/components/WeatherCard/WeatherCard.tsx
import * as React from "react";
import { Card, Avatar } from "antd";
import { IWeatherCard } from './WeatherCardProps';

const { Meta } = Card;

class WeatherCard extends React.Component<IWeatherCard, any> {
  constructor(props: any) {
    super(props);
  }

  private kelvinToCelsius = (temp: number): number => Math.round(temp - 273.15);

  public render() {
    return (
      <div>
        <Card className="Card">
          <Meta
            avatar={<Avatar src={`http://openweathermap.org/img/w/${this.props.weather[0].icon}.png`}size="large"/>}
            title={
              <div>
                <p>{this.props.weather[0].main}</p>
                <h3>{this.kelvinToCelsius(this.props.main.temp) + "°C"}</h3>
              </div>
            }
            description={this.props.dt_txt}
          />
        </Card>
      </div>
    );
  }
}

export default WeatherCard;
```
[antd](https://ant.design/)というDesign Componentを使い受け取ったデータをCardとして配置する。

```src/components/WeatherCardList/WeatherCardList.tsx
import * as React from "react";
import * as request from "superagent";
import { IWeatherCard } from '../WeatherCard/WeatherCardProps';
import WeatherCard from '../WeatherCard/WeatherCard';

interface IWeatherCardList {
  weatherCards: IWeatherCard[];
}

class WeatherCardList extends React.Component<any, IWeatherCardList> {
  constructor(props: any) {
    super(props);
    this.state = {
      weatherCards: []
    };
  }

  public componentWillMount() {
    request
      .get("http://api.openweathermap.org/data/2.5/forecast")
      .query({
        q: "Hakodate",
        appid: "APIKey"
      })
      .then(response => response.body.list)
      .then(body => {
        console.log(body);
        this.setState({
          weatherCards: body
        });
        console.log(JSON.stringify(this.state.weatherCards));
      })
      .catch(error => {
        console.log(error);
        throw error;
      });
  }
  public render() {
    const resultNodes = this.state.weatherCards.map(weatherCard => {
      return <WeatherCard key={weatherCard.dt} {...weatherCard} />;
    });

    return (
    <div>
        <h1>函館お天気情報</h1>
        <p>Hakodate Weather Information</p>
        <ul>{resultNodes}</ul>
    </div>
    )};
}

export default WeatherCardList;
```
componentWillMount()を用いてOpenWeatherMapAPIを叩く。その際、[superagent](https://github.com/visionmedia/superagent)というライブラリを使用する。queryとしてqには自分の天気を知りたい市を、appidには自分のAPIKeyを入れる。
あとは、renderでWeatherCardの個数分回してresultNodesに代入したら、それを表示するだけです。

## 最後に
今回cssについてはあまり触れていません。一応https://github.com/butachin/Weather-App には書いてあるので興味があったら見てください。わかりづらいとは思いますが、こんな感じで簡単にWebアプリが作れます。よかったら参考にしてください。