React HooksでCovid19トラッカーアプリを作った

## はじめに

Reactの練習、特にHooks×Web APIを習得するために構築しました。
Covid19のデータはdisease.shのAPIから取得しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438597/c2f44d2d-fe44-456d-8e5a-4f124cb8c3f1.png)

サイトの内容としては、世界各国のCoronaViruses Cases, Deaths, Recoverdの統計を確認できます。
国をメニューから選択すると、マップやグラフもそれに応じた内容が表示されます。ReactのHooksによるState管理は本当に強力ですね。それでいてシンプルで書きやすく、生産性が非常に高いです。

[DEMO URL](https://covid19-tracker-react-55a37.web.app/)
[githubレポジトリ](https://github.com/newt0/covid19-tracker-react)

Reactの最新の書き方に則ったコードを心掛けているので、Reactを勉強中の方にはGithubレポジトリが参考になると思います。


## 使用技術

- React
- JavaScript(ES6)
- Hooks
- Functional Component
- firebase(Hosting)
- Material UI
- react-chartjs-2
- react-leaflet
- BEM


### Functional Programming

Functional Component(関数コンポーネント)のみ使用してます。Class Componentは一切使用していません。
Functional Component(関数コンポーネント), Destructuring assignment(分割代入),Hooksを併用することでReactのコードは驚くほどシンプルかつ綺麗になります。
既存のClass Componentをわざわざ書き換える必要はありませんが、今後は基本的にFunctional Componentを使用するべきでしょう。


### Web API

Covid19のデータはdisease.shのAPIから取得しています。
`useEffect()`内で`fetch()`して、`useState()`で状態管理しています。

``` App.js
function App() {
  const [countries, setCountries] = useState([]);
  const [country, setCountry] = useState("worldwide");
  const [countryInfo, setCountryInfo] = useState({});
  const [tableData, setTableData] = useState([]);
  const [mapCenter, setMapCenter] = useState({ lat: 34.80746, lng: -40.4796 });
  const [mapZoom, setMapZoom] = useState(3);
  const [mapCountries, setMapCountries] = useState([]);
  const [casesType, setCasesType] = useState("cases");

  useEffect(() => {
    fetch("https://disease.sh/v3/covid-19/all")
      .then((response) => response.json())
      .then((data) => {
        setCountryInfo(data);
      });
  }, []);

  useEffect(() => {
    const getCountriesData = async () => {
      await fetch("https://disease.sh/v3/covid-19/countries")
        .then((response) => response.json())
        .then((data) => {
          const countries = data.map((country) => ({
            name: country.country,
            value: country.countryInfo.iso2,
          }));

          const sortedData = sortData(data);
          setTableData(sortedData);
          setCountries(countries);
          setMapCountries(data);
        });
    };

    getCountriesData();
  }, []);

  const onCountryChange = async (event) => {
    const countryCode = event.target.value;
    setCountry(countryCode);

    const url =
      countryCode === "worldwide"
        ? "https://disease.sh/v3/covid-19/all"
        : `https://disease.sh/v3/covid-19/countries/${countryCode}`;

    await fetch(url)
      .then((response) => response.json())
      .then((data) => {
        setCountry(countryCode);

        // all of the data from the country response
        setCountryInfo(data);
        // setMapCenter([data.countryInfo.lat, data.countryInfo.long]);
        setMapCenter({ lat: data.countryInfo.lat, lng: data.countryInfo.long });
        setMapZoom(4);
      });
  };

// 以下略
```

### フロント

CardやMenu等主要なコンポーネントはMaterial UIを使用しているので、ものすごくラクです。
Material UIは本当に便利です。NuxtではVuetifyを使用していましたが、個人的にはReactのMaterial UIの方がしっくりきます。
FlexboxはじめスタイリングはBEMに基づきCSSを書いているのですが、なるべくMarerial UIのヘルパーで済ませた方が良かったかもしれません。

チャートはreact-chartjs-2、マップはreact-leafletというライブラリをそれぞれ使用しています。


## 今後やりたいこと

今回のサイトはあくまで練習として作りました。Reactの実力はかなり付けることができたと思います。

### ローカライズしたい

日本国内の東北地方のCovid19トラッカーサイトを作りたいです。なので、データを取得するAPIを変更する必要があります。


### SNS自動投稿

Webサイトとは別に、Twitterにその日のデータを自動で投稿する機能をつけたいです。サイトを開くのは億劫なので、Twitterで簡単に情報を確認できた方が便利かなと。


##  参考

[React開発効率を3倍にするVS Code拡張機能&環境設定](https://qiita.com/newt0/items/b7810fb38c339ec5e4a7)
[React初案件獲得までの流れ(学習・案件探し・面接・契約まで)](https://qiita.com/newt0/items/975a379de904858dd0f9)

[The Complete React Developer Course (w/ Hooks and Redux)](https://www.udemy.com/course/react-2nd-edition/)
[Universal React with Next.js - The Ultimate Guide](https://px.a8.net/svt/ejp?a8mat=3BK8OP+16V8C2+3L4M+BW8O2&a8ejpredirect=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Funiversal-react-with-nextjs-the-ultimate-guide%2F)
[React Native入門：ニュースアプリを作りながら覚えよう/Hooks対応 2020年版](https://px.a8.net/svt/ejp?a8mat=3BK8OP+16V8C2+3L4M+BW8O2&a8ejpredirect=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Freact-native-first-step%2F)
[React.js & Next.js超入門](https://amzn.to/2WwaXwQ)
[実践Firestore](https://amzn.to/3auotcD)
[初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発](https://amzn.to/3h0S7aJ)

<a href="https://www.amazon.co.jp/dp/B07X7DHZ9F/ref=as_li_ss_il?&linkCode=li2&tag=fden02-22&linkId=0b5b3306ff6ecee8f89a30f15b492aa9&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B07X7DHZ9F&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=fden02-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=fden02-22&language=ja_JP&l=li2&o=9&a=B07X7DHZ9F" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /><a href="https://www.amazon.co.jp/dp/B0851BGDQG/ref=as_li_ss_il?&linkCode=li2&tag=fden02-22&linkId=fedb0f3b6f6cc9bbc2a5b25b79509ef5&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B0851BGDQG&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=fden02-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=fden02-22&language=ja_JP&l=li2&o=9&a=B0851BGDQG" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /><a href="https://www.amazon.co.jp/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEJavaScript-%E7%AC%AC3%E7%89%88-%E2%80%95ES2015%E4%BB%A5%E9%99%8D%E3%81%AE%E6%9C%80%E6%96%B0%E3%82%A6%E3%82%A7%E3%83%96%E9%96%8B%E7%99%BA-Ethan-Brown/dp/4873117836/ref=as_li_ss_il?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=298855TL8IQBA&dchild=1&keywords=javascript&qid=1608361534&sprefix=JavSc,aps,270&sr=8-18&linkCode=li2&tag=fden02-22&linkId=9eb63941ebf502c87942606420c6108a&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4873117836&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=fden02-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=fden02-22&language=ja_JP&l=li2&o=9&a=4873117836" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />