ReactNativeで天気予報アプリ作ってみた

# 作成したアプリ
![giphy.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1973408/84e716a2-d3cf-6cac-8f38-8a9a60b8eac4.gif)




# 使用した技術
1.ReactNative
2.OpenWeatherMap API
3.GoogleMap API
4.moment.js

## 事前準備
[OpenWeatherMapAPI](https://home.openweathermap.org/users/sign_up)のアカウントを作成する

<font color=red><strong>アカウントを作成したらIDをもらえるのでメモかどこかに保存しておいてください。</font>

詳しく書いている記事があったので参考にしてみてください。
https://yuukiyg.hatenablog.jp/entry/2019/11/17/182410

# 開発環境構築


## 1. ReactNativeを動かすためのツールのインストール
```
npm install -g react-native-cli
brew install node
brew install watchman
sudo gem install cocoapods
```
[cocoapods](https://cocoapods.org/)というのはiosのライブラリ管理ツールです。


## 2. プロジェクトの作成
```
react-native init <プロジェクト名>
```

## 3. 起動してみる
```
cd <プロジェクト名>
```
で２で作成したディレクトリに移動して

```
react-native run-ios
```
で起動!
<img width="200px" alt="正しくビルドできた時の写真" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1973408/c30d0355-dab9-210c-79ef-e93feb1a3206.png">
正しくビルドできてたらこんなシミュレーターが起動します。


# 作成開始！
ここからは自分が作成したアプリで、重要な部分を切り抜いて書いていきます！
App.jsを書き換えることでアプリを作成できます。

現在位置を取得するためにライブラリをインストールしよう！
詳しくは[こちら](https://github.com/react-native-geolocation/react-native-geolocation)

```
npm install @react-native-community/geolocation --save
```

# OpenWeatherMapAPIからデータを取得する

```ReactNative:App.js
const [data, setData] = useState({});

  useEffect(() => {
    Geolocation.getCurrentPosition(
      position =>
        getWether(position.coords.latitude, position.coords.longitude),
      err => console.log(err.message),
      {enableHighAccuracy: true, timeout: 10000, maximumAge: 10000},
    );
  }, []);

  const getWether = async (lat, lon) => {
    const query_params = new URLSearchParams({
      appid: 'OpenWeatherMapのID',
      lat: lat, //緯度
      lon: lon, //経度
      units: 'metric', //温度の単位を摂氏に
    });
    const response = await fetch(
      'https://api.openweathermap.org/data/2.5/onecall?' + query_params,
    );
    const weatherData = await response.json();
    setData(weatherData);
    // console.log(JSON.stringify(weatherData) + 'aaaa');
  };
```
マウントした時（アプリを起動した時）に現在位置を取得します。
useEffectの第２引数で空の配列を渡せばマウント時のみ処理が走る！！

getWeather関数は非同期処理で書かないと、取得完了する前にステートに代入してしまうので注意!
[事前準備](#事前準備)で取得したIDをURLのパラメータに入れます。

**小話**
fetchのURLのonecallの部分をweatherとかhourlyとかに書き換えることで
天気情報の取得する期間を変えることができます！ 詳しくは[こちら](https://openweathermap.org/api)

```
const response = await fetch(
      'https://api.openweathermap.org/data/2.5/<この部分に何を入れるかで変わる>?' + query_params,
    );
```

onecallで取得できる天気情報　　
[公式ドキュメント](https://openweathermap.org/api/one-call-api)を見たらよくわかります！！

```
{
  "lat": 35.68,
  "lon": 139.77,
  "timezone": "Asia/Tokyo",
  "timezone_offset": 32400,
  "current": {
    ...(略)...
  },
  "hourly": [
    {
      ...(略)...
    },
    ...(略)...
    {
      ...(略)...
    }
  ],
  "daily": [
    {
      ...(略)...
    },
    ...(略)...
    {
      ...(略)...
    }
  ]
}
```




## ~~momentで時刻データを加工しよう！~~

<font color=red><strong>moment.jsがメンテナンスモードになっているため他ライブラリの使用してください。</font>
day.jsやdate-fnsがお勧めです。詳しく解説してくれている[記事](https://zenn.dev/imaginelab/articles/68de83f4948fe2)を共有します。


momentをインストール

```
npm install moment 
npm install moment-timezone //timezoneを使えるようにする
```
OpenWeatherMapAPIから取得したjsonデータにはUNIXの形式で時間データが入っています。
それをmoment.jsを使って現地時間に合わせるかつ、表示形式を変えていきます！



```ReactNative:DateTime.js/一部抜粋
moment(current.sunrise, 'X').tz(timezone).format("HH:mm")
```
momentの第２引数'X'はcurrent.sunriseがUNIX形式ですよ！と示しています。
という認識です。。。ここ自信ないのでわかる方教えてください！
そしてtimezoneを指定することで現地時間で何時なのかを計算します。
formatを指定すれば表示形式を指定できます。HHをhhにするとAMPM表示にできます。

momentについて解説してくれている記事があったので共有します。
https://www.wakuwakubank.com/posts/606-javascript-moment/


#MAPを表示させる
私はGoogleMap APIを使ってみたかったので使いましたが、使わなくてもMapを表示させることができます。
使ってみたい方は参考になれば嬉しいです！
以下iosについて解説　Android版は[こちら](https://zenn.dev/nekoniki/articles/0c40e9267b81e4)←参考にさせてもらった記事

GoogleMap APIを使うためには[GCP](GoogleMap API)でプロジェクトを作成する必要があります。
作成できたら【API設定】からMaps SDK for iOS or Maps SDK for Androidを有効化します。
<img width="500px" alt="正しくビルドできた時の写真" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1973408/6a2e155c-a378-c90f-031d-21cb2bb2c1e4.png">
画面の案内に従って、Maps SDK for iOSのAPIキーを取得します
`ios/[project]/AppDelegete.m`に取得したAPIキーを入力します。



```AppDelegete.m
#import<GoogleMaps/GoogleMaps.h>  // 追加

// ...略

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [GMSServices provideAPIKey:@"【取得したAPI_KEY】"]; // 追加
}
```
そして`ios/Podfile`に以下を追加します。

```Podfile
pod 'react-native-google-maps', path:'../node_modules/react-native-maps'
pod 'GoogleMaps'
pod 'Google-Maps-iOS-Utils'
```

App.jsに以下を記述することでMapを表示することができます。
Markerを使うことでMap上にピンを立てることができます。

```ReactNative:App.js
 <MapView
    provider={PROVIDER_GOOGLE}
　　　　　　　　style={height: '50%',width: '70%',}
    region={{
    latitude: data.lat,
    longitude: data.lon,
    latitudeDelta: 0.0922,
    longitudeDelta: 0.0421,
　　　}}>
   <Marker coordinate={{latitude: data.lat, longitude: data.lon}} />
</MapView>
```
#アプリを完成させる！
あとはOpenWeatherMapAPIから取得したデータを使ってレイアウトを考えてコードを書いていくだけ！
githubに載っけているのでよかったら見てください！！
https://github.com/kenjirohayashi/weatherApp


#まとめ
ざっと使用した技術について説明しましたが、間違っていることがあったりアドバイスがあればドシドシコメントください！！
いつもAPIの提供や様々な方の記事やブログに助けられてます。感謝です！！
この記事も誰かのためになれば幸いです！

#参考文献
https://openweathermap.org/api
https://yuukiyg.hatenablog.jp/entry/2019/11/17/182410
https://www.wakuwakubank.com/posts/606-javascript-moment/
https://zenn.dev/nekoniki/articles/0c40e9267b81e4