Reactを使ったお天気アプリを作成してみた


はじめに

Reactを学習していくにあたり、REST APIの勉強を兼ねてお天気アプリを作成してみました。

ソースコードのビルドにはOpenWeather APIのAPIキーとGoogle Maps APIのキーが必要となります。

仕様について

今回、天気アプリ作成にあたり、まず仕様について下記のように項目出しを行いました。

あらかじめおおざっぱながらも機能を書き出すことで自分が何から手をつけていくのがよいか、また途中で迷子にならないよう進行することができたと思います。

  • ページを表示した時に、WebAPIのgeolocationAPI(位置情報API)を利用して現在地の緯度経度を取得する
  • 取得した緯度経度を使ってOpenWeatherAPI経由で天気情報を取得する
  • 取得した天気情報を使って現在地付近の情報を表示する
    • 取得日時を表示する
    • 天気アイコンを表示する
    • 現在の気温を表示する
    • 体感温度を表示する
    • 最高気温を表示する
    • 最低気温を表示する
    • 風向きを表示する
    • 風速を表示する
    • 気圧を表示する
    • 湿度を表示する
    • 7日間予報を表示する
    • 1時間ごとの予想気温をグラフで表示する
  • 地名から検索ができる

利用サービス・利用技術

突然のテスト駆動開発へ挑戦

前回ポートフォリオサイトを作ったときにはStorybookへ挑戦したのですが、今回はテストを書いてみるというテーマで開発を開始しました。

テストについて色々と調べていくと気になったのがテスト駆動開発という言葉。前々から言葉だけは聞いたことがあったのですが、実際にはどういった手法になっているのかまったく知らなかったため和田卓人氏の下記講演の視聴から勉強してみました。

さらに上記講演をReactのフロントエンド開発に置き換えた解説記事も参考にしながら、手を動かしていきます。

が、すぐに車輪は止まりました笑

自分にはまだ早かったのか、タスクの粒度を細かくしていくことができず複雑怪奇になってしまい、結局部分的なテストコードしか書いていくことができませんでした。。。

テストを書くということ自体にはとても感銘を受けたので、今後もテストについては勉強を続けながら書いていこうと思います。

emotionを試す

今回スタイルにつていはemotionのcss Propを使ってみました。

Create React App、TypeScript環境で利用するにはひと手間必要で、

ソースの先頭に下記1行を追記する必要があります。

/** @jsxImportSource @emotion/react */

一例として今回ローディング画面で利用したスケルトンコンポーネントは下記のようになっています。

/src/components/atoms/Button/index.tsx
/** @jsxImportSource @emotion/react */
import React from 'react';
import { css, keyframes } from '@emotion/react';

export type Props = {
  height?: string;
  width?: string;
  radius?: string;
};

const Skelton: React.VFC<Props> = (props) => {
  const { height = '1.5rem', width = '100%', radius = '0' } = props;

  return (
    <div
      css={skeltonStyle}
      style={{ width: `${width}`, height: `${height}`, borderRadius: `${radius}` }}
    />
  );
};

export default Skelton;

const skeltonAnimation = keyframes`
  0% {
    transform: translateX(-100%)
  }
  100% {
    transform: translateX(100%)
  }
`;

const skeltonStyle = css`
  width: 100%;
  height: 1.5rem;
  line-height: 2;
  background: #d9d9d9;
  position: relative;
  overflow: hidden;
  margin: 0.5rem 0;
  &::before {
    content: '';
    display: block;
    height: 100%;
    width: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
    position: absolute;
    top: 0;
    left: 0;
    z-index: 100;
    animation: ${skeltonAnimation} 1.2s linear infinite;
  }
`;

私のVS Code環境だとcss Propを利用すると css`` を利用したあとのシンタックスハイライトがなんだかおかしくなるので下の方に追いやっています。個人的なイメージとしてはvue.jsの<style>ブロックみたいな雰囲気に感じました。

苦労した点

位置情報APIの取得、そこからOpenWeatherAPIの取得、Googleマップの表示と非同期処理の完了を待って、また次の非同期処理へという流れが続く部分でかなり混乱してしまいました。

上記にあわせてuseStateが変数を格納するタイミング、useEffectの実行タイミングの理解も曖昧だったため、さらに悪循環にはまっていきましたが、ひとつずつconsole.logで動きを確かめながら解消していきました。

さいごに

今回はテストコードの記載に挑戦しながらアプリを作成してみましたのですが、テストコードを書くことを通じて根本的なロジックというかプログラムの考え方を少しだけ知ることができました。このアプリのテストコードをもう少し書き進めながら、次の制作物でも引き続きテストコードに挑戦していこうと思います。

関連記事

参考サイト

位置情報API(geolocation API)

Google Maps API

TDD、jest、React Testing Library

Chart.js

emotion css prop