ReactとTailwind CSSフレームワークを使い天気のアプリケーションを作成することでReact Hooks、Fetch関数、propsのReactの基本的な使い方を紹介しています。

React.js環境にCSSフレームワークのTailwind CSSの設定を行った後、Tailwind CSSで作成したWeatherコンポーネントを作成します。作成したWeatherコンポーネントからAPI経由でOpenWeatherサービスから天気の情報を取得し4つの都市の天気の情報をブラウザ上に表示させます。

Reactの基本的な知識のみで作成することができるのでReact入門者の人向けの文書になっています。

4つの都市の天気を表示
4つの都市の天気を表示

天気アプリケーションを作成する中で以下のことを学ぶことができます。

  • React環境でのTailwind CSSの設定方法
  • Tailwind CSSの使い方
  • APIを使った天気情報の取得方法(OpenWeather)
  • Reach Hooksの使い方(useState, useEffect)
  • コンポーネントへのpropsの渡し方

Reactの環境構築

Reactプロジェクトの環境を構築するためにはnode.jsがインストールされている必要があります。node -vコマンドを実行してバージョンが表示されない場合はnode.jsのインストールを行ってからReact環境の構築を行ってください。

npx create-react-appコマンドを実行して、新規のReactプロジェクトを作成します。プロジェクトの名前をtailwindcss_weatherとしていますが任意の名前をつけてください。


 % npx create-react-app tailwindcss_weather

プロジェクト作成後、プロジェクトフォルダに移動してnpm startを実行してReactが動作するか確認します。


 % cd tailwindcss_weather
 % npm start

ブラウザが自動で起動し下記の画面が表示されます。

React初期画面
React初期画面

Tailwind CSSのインストールと設定

Reactの動作確認ができたのでTailwind CSSのインストールを行います。インストールと初期設定についてはTailwind CSSの公式のドキュメントを参考に行います。Tailwind CSSを使ったことがない人は以下の文書が参考になります。

npmコマンドを利用してTailwind CSSをインストールします。


 % npm install -D tailwindcss@npm:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9

ReactでTailwind CSSを利用するためにはCRACOが必要となるため、CRACOのインストールを行います。


 % npm install @craco/craco

CRACOのインストールが完了したら、 プロジェクトフォルダにあるpackage.jsonを更新します。


//略
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
  },
//略

プロジェクトフォルダの直下にCRACOの設定ファイルであるcraco.config.jsファイルを作成します。


 % touch craco.config.js

craco.config.jsファイルに以下を記述します。


module.exports = {
  style: {
    postcss: {
      plugins: [
        require('tailwindcss'),
        require('autoprefixer'),
      ],
    },
  },
}

Tailwind CSSの設定ファイルであるtailwind.config.jsファイルを作成するために以下のコマンドを実行します。


 % npx tailwindcss init
  
   @tailwindcss/postcss7-compat 2.0.3
  
   ✅ Created Tailwind config file: tailwind.config.js

プロジェクトフォルダ直下にtailwind.config.jsファイルが作成されます。Productionの際は、アプリケーションの中で利用していないTailwind CSSのClassをバンドルファイルに含まないために下記の設定を行います。利用しないClassを含めすべてのClassが含まれているとバンドルファイルのサイズが大きくなるためです。参考に載せていますがbuildした時のみ有効になるので今回のような学習のための動作確認にはこの設定を行う必要はありません。

tailwind.config.jsファイルのpurgeプロパティの値を更新しています。


module.exports = {
  purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}

ここからは必須の作業です。Tailwind CSSのclassを利用できるように@tailwindcssディレクティブを使ってsrcフォルダにあるindex.cssを更新します。


@tailwind base;
@tailwind components;
@tailwind utilities;

srcフォルダにあるindex.jsファイルにindex.cssファイルがimportされているか確認します。デフォルトではindex.cssはimportされているので何も行う必要はありませんが念の為確認しておきます。

これでReactにおけるTailwind CSSの設定は完了です。設定完了後は、Tailwind CSSが有効になっているのか確認していましょう。

App.jsファイルを開いての画面中央に文字が表示されるようにTailwind CSSのClassを設定します。


function App() {
  return (
    <div className="min-h-screen flex justify-center items-center">
      Weather Application
    </div>
  );
}

export default App;

ブラウザの画面中央に文字が表示されたらTailwind CSSの設定が適切に行われ正常に動作していることになります。

Tailwind CSSの設定
Tailwind CSSの設定

Weatherカードの作成

APIを利用して外部のサービスであるOpenWeatherから天気の情報を取得する前に取得した情報を表示するためのカードコンポーネントを作成します。カードはコンポーネント化するためにApp.jsとは別ファイルとして作成します。Weather.jsファイルはsrcフォルダの下に作成します。幅はw-96(24rem)、高さはh-56(14rem)、背景色はブルーの四角を設定しています。


function Weather() {
  return (
    <div className="p-4">
      <div className="w-96 h-56 m-auto bg-blue-500">
      </div>
    </div>
  )
}

export default Weather

App.jsファイルでは作成したWeather.jsファイルをimportします。


import Weather from "./Weather"
function App() {
  return (
    <div className="min-h-screen flex justify-center items-center">
      <Weather />
    </div>
  );
}

export default App;

ブラウザの中央には背景がブルーの四角が表示されます。

ブラウザ上に青い四角が表示
ブラウザ上に青い四角が表示

角に丸み(rounded-xl)をつけて、シャドウ(shadow-2xl)をつけます。


<div className="w-96 h-56 m-auto bg-blue-500 rounded-xl shadow-2xl">
box-shadowとborder-radiusを設定
丸みとシャドウを設定

マウスオーバーするとサイズが大きくなるようにtransfromの設定を行います。四角がゆっくりと浮き上がってくるように見えるようにtransitionの設定も行います。設定後はマウスオーバーしてサイズがふわっと大きくなることを確認してください。


<div className="w-96 h-56 m-auto bg-blue-500 rounded-xl 
                   shadow-2xl 
                   transform hover:scale-110 transition-transform ">

背景にグラデーションの設定を行います。


<div className="bg-gradient-to-r from-blue-500 to-blue-300
                w-96 h-56 m-auto rounded-xl 
                shadow-2xl transform hover:scale-110 
                transition-transform ">

bg-gradient-to-r、from-blue-500, to-blue-300を設定すると左から色の濃いblue-500から色の薄いblue-300へと変わるグラデーションが設定できます。

グラデーションの入った四角
グラデーションの入った四角

グラデーションの入った四角が作成できたら天気の情報を表示させる四角の内部の設定を行っていきます。都市の名前と天気の画像を表示される場所を作成します。


<div className="bg-gradient-to-r from-blue-500 to-blue-300
                w-96 h-56 m-auto rounded-xl shadow-2xl 
                transform hover:scale-110 transition-transform
                text-white relative">           
  <div className="w-full px-8 absolute top-6">
    <div className="flex justify-between">
      <div>
        <p className="font-light">City Name</p>
        <p className="text-lg font-medium tracking-widest">
          Tokyo
        </p>
      </div>
      <div>
        画像
      </div>
    </div>
  </div>
</div>

flexboxのjustify-betweenで文字と画像の場所を両端になるように設定しています。tracking-widestは文字間隔、font-medium, font-lightで文字の太さの調整、text-logで文字の大きさを設定しています。文字の色もtext-whiteで白に設定しています。位置を調整するためpaddingとrelative, absoluteで設定を行っています。

ブラウザで確認すると左側には都市名、右側には画像の文字が白で表示されます。画像の部分は後ほど文字ではなく画像が表示できるように設定を行います。

文字と画像の場所を追加
文字と画像の場所を追加

カード内に表示する天候、気温、湿度、日時のもTailwind CSSを使って装飾を行います。カード全体では下記のようなHTML文となります。


<div className="p-4">
  <div className="bg-gradient-to-r from-blue-500 to-blue-300
                  w-96 h-56 m-auto rounded-xl shadow-2xl 
                  transform hover:scale-110 transition-transform
                  text-white relative">           
    <div className="w-full px-8 absolute top-6">
      <div className="flex justify-between">
        <div>
          <p className="font-light">City Name</p>
          <p className="text-lg font-medium tracking-widest">
            Tokyo
          </p>
        </div>
        <div>
          画像
        </div>
      </div>
      <div className="pt-2">
        <p className="font-light">Weather Condition</p>
        <p className="text-lg font-medium tracking-widest">
          Cloudy
        </p>
      </div>
      <div className="pt-6 pr-6">
        <div className="flex justify-between">
          <div>
            <p className="font-light text-xs">
                Date
            </p>
            <p className="font-bold tracking-more-wider text-sm">
              2021-03-16
            </p>
          </div>
          <div>
            <p className="font-light text-xs">
              Temprature
            </p>
            <p className="font-bold tracking-more-wider text-sm">
              20°C
            </p>
          </div>
          <div>
            <p className="font-light text-xs">
              Humidity
            </p>
            <p className="font-bold tracking-more-wider text-sm">
              40%
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

ブラウザで確認すると下記のカードデザインが作成できます。文字はすべて直接記述していますがこの後OpenWeatherサービスから取得したデータに置き換えていきます。

カードの作成
カードの作成

OpenWeatherのAPI

アカウントの作成

天気を表示するためのカードコンポーネントを作成したので次は天気の情報をAPIを利用して取得します。今回は無料で利用できるOpenWetherサービスを利用します。OpenWeatherを利用するためにはアカウントの作成が必要となるためアカウントの作成を行います。

OpenWeatherのサイトにアクセスします。ページの右上にある”Sing in”ボタンをクリックしてください。

OpenWeatherのトップページ
OpenWeatherのトップページ

サインインの画面が表示されますがアカウントの作成ができていないので”Create an Account”をクリックしてください。

Sign inページ
Sign inページ

アカウント作成ページが表示されるので必要な項目を入力して”Create Account”ボタンをクリックしてください。

アカウント作成ボタン
アカウント作成ボタン

アカウント作成後に会社名と目的の入力フォームが表示されますが”Cancel”を選択することも可能です。

アカウント作成後の質問
アカウント作成後の質問

登録したメールアドレス宛にメールアドレスの確認メールが来ているのでメールを開き、”Verify your email”をクリックしてください。

メールアドレスの確認
メールアドレスの確認

APIのKeyの確認

アカウントが作成できるとデフォルトのAPI Keyを利用することができます。デフォルトのAPI Keyは表示されていますが利用できるまでに少し時間がかかる場合があります。利用ができない時にAPI keysでアクセスすると401 unauthorizedエラーが表示されます。

API keysのタグをクリックすると名前がDefaultのKeyを利用することができます。Keyは追加するこも可能です。

APIキーを確認する
APIキーを確認する

このDefaultのKeyを利用してOpenWeatherから天気の情報を取得します。

APIの利用方法の確認

APIを利用して外部のサービスから情報を取得するためには主に3つの情報が必要となります。1つは先ほど取得したAPIキー、2つ目はアクセスを行うURLで3つ目はパラメータです。それらの情報はドキュメントに記載されているのでドキュメントを確認する必要があります。

OpenWeaterの上部にあるAPIタグをクリックすると利用できるWether APIが表示されます。今回はCurrent Weather Data(現在の天候データ)を利用するので”API Doc”をクリックしてください。

ドキュメントの確認
ドキュメントの確認

ページを開くとすぐにAPIのURLとパラメータを確認することができます。q=に都市名とappidにKeyを設定することで現在のその都市の天気の情報が取得できることがわかります。ページをスクロールすると都市名だけではなく郵便番号や緯度、経度などでも取得できることがわかります。アクセス後に戻される情報のJSONの構造も記述されているのでしっかりと確認しておきしょう。構造については後ほど確認します。

APIの情報
APIの情報

ブラウザからの天気の取得

東京の現在の天気を取得してみましょう。URLとパラメータ、APIキーがわかっているのでブラウザからも取得することができます。ドキュメントに記載されたルールにしたがってURLを作成し、ブラウザのURL欄に記述します。


http://api.openweathermap.org/data/2.5/weather?q=TOKYO&appid=00b0681054136c5fXXXXXXXXXX

下記のようにブラウザ上にはOpenWeatherから戻されたJSONデータが表示されます。

直接ブラウザからアクセス
直接ブラウザからアクセス

Reactの設定

APIの設定

OpenWeatherのURLやAPIKeyについては.envファイルの中に保存し、Weatherコンポーネントからは.envに設定した環境変数からそれらの値を取得して利用します。

プロジェクトフォルダの下に.envファイルを作成してください。それぞれの変数には任意の名前をつけることができますが先頭にはREACT_APPをつけてください。REACT_APP_OW_API_URLの値はOpenWeatherの全API共通のURLで現在の天気以外の天気予報などのAPIでも利用することができます。REACT_APP_OW_API_KEYについては各自の環境によって異なる値を設定します。REACT_APP_OW_ICON_URLはOpenWeateherが提供する天気のアイコン画像のURLです。アイコンについてはOpenWeatherから戻されるJSONデータの中に画像に関する情報が含まれています。後ほど説明を行います。


REACT_APP_OW_API_URL='api.openweathermap.org/data/2.5'
REACT_APP_OW_API_KEY='00b0681054136cXXXXXXXXXXXXXXXXXX'
REACT_APP_OW_ICON_URL='https://openweathermap.org/img/w'

Reactからの天気情報の取得

ブラウザから天気の情報が取得できることは確認できているのでReact上からAPIを使ってOpenWeatherにアクセスを行い天気情報を取得します。

React HooksのuseEffectを利用するのでWeather.jsファイルにuseEffectをimportします。userEffectを利用することでWeatherコンポーネントのマウント時にfetch関数で天気の情報を取得しています。


import { useEffect } from 'react';

function Weather() {

  useEffect(()=>{
    fetch(`${process.env.REACT_APP_OW_API_URL}/weather/?q=Tokyo&APPID=${process.env.REACT_APP_OW_API_KEY}`)
    .then(res => res.json())
    .then(result => {
      console.log(result);
    });
  },[]);

  //略

ブラウザのコンソールに取得した情報が表示されます。取得したデータのnameからTokyoが確認できますが、tempが294.65となっているので摂氏で取得できるようにfetch関数でアクセスするURLに&units=metricを追加します。

天気情報を取得
天気情報を取得
1分間に60コール以上を実行するとYour account is temporary blocked due to exceeding of requests limitation of your subscription type. Please choose the proper subscription http://openweathermap.org/priceとメッセージが表示され、一時的に利用できなくなります。useEffectを利用する場合は第2引数に注意して設定を行ってください。

取得した情報をブラウザ上にで利用するためには変数に保存する必要があります。変数に保存するためにReact HooksのuseStateを利用します。useEffectと同様にimportが必要となります。

取得したデータを保存する変数をdataとして初期値には空の配列を設定しています。


import { useState, useEffect } from 'react';
function Weather() {

  const [data, setData] = useState([]);

  useEffect(()=>{
    fetch(`${process.env.REACT_APP_OW_API_URL}/weather/?q=Tokyo&APPID=${process.env.REACT_APP_OW_API_KEY}&units=metric`)
    .then(res => res.json())
    .then(result => {
      setData(result);
  },[])

  //略

保存したdataをブラウザ上に表示させるためにはOpenWeatherから取得したJSONデータの構造を理解しておく必要があります。

ブラウザ上に表示させたい気温(temp)はmainの中にオブジェクトとして保存されており、天気の情報はweatherの中に配列として保存されています。weatherの配列にあるiconプロパティの02nが画像の情報を表しています。

JSONデータを確認
JSONデータを確認

JSONのデータ構造がわかったのでブラウズ上に表示できるように保存したdataを展開してみましょう。

dataのnameに都市名が含まれているのでこれまでTokyoと直接記述していた部分をdata.nameに変更します。


<p className="text-lg font-medium tracking-widest">
  { data.name }
</p>

ブラウザ上にはTokyoと表示されます。

カードの作成
data.nameの中身を表示

つぎに天候を表すWeather Conditionの値をdata.weather[0].mainに変更します。weatherの配列のmainに天候情報が入っているためです。


<p className="text-lg font-medium tracking-widest">
  { data.weather[0].main }
  //Cloudy
</p>

しかしブラウザ上には先ほどのdata.nameとは異なりundefinedエラーが表示されます。undefinedが表示されるので配列へのアクセス方法の処理を疑いますが原因はそれではありません。原因はOpenWeatherからデータを取得し変数dataに値を保存する前にブラウザ上での描写処理が行われるためまだ存在していなdataのweatherプロパティの中身にアクセスしようとしているためです。

undefinedエラーが発生
undefinedエラーが発生

この問題を解決するにはOpenWeatherからのデータを取得後に描写処理を行わせる必要があります。新たに変数loadingを追加し、OpenWeatherからデータ取得後にloadingの値を変更しloadingの値の変化で取得が完了したかどうかを判定します。loadingの初期値をtrueとし、データの取得が完了したらfalseに設定します。loadingの値がtrueの間は<div></div>が表示され、loadingがfalseになったらWeatherのカード部分が表示されます。


import { useState, useEffect } from 'react';
function Weather() {

  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(()=>{
    fetch(`${process.env.REACT_APP_OW_API_URL}/weather/?q=Tokyo&APPID=${process.env.REACT_APP_OW_API_KEY}&units=metric`)
    .then(res => res.json())
    .then(result => {
      setData(result);
      setLoading(false);
    })
  },[])

  if (loading) {
    return <div></div>;
  }

  return (
    <div className="p-4">
    //略

再度動作確認するとエラーは解消されWeather ConditionにCloudsと表示されました。先ほどまでは直接Cloudyと記述していたのでOpenWeatherから取得したデータが反映されていることがわかります。

現在の東京の天気を表示
現在の東京の天気を表示

loadingのtrueの場合は空の<div></div>を設定していましたがTailwind CSSを利用することで簡単にローディングを表示させることができます。実際に追加するとWeatherのカードの中身が表示される前に一瞬ローディングが表示されることが確認できます。


if (loading) {
  return <div>
    <svg className="animate-spin -ml-1 mr-3 h-5 w-5 text-blue-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
      <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
      <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
    </svg></div>;
}
Loadingが一瞬表示される
Loadingが一瞬表示される

日付についてはdtの中にUnixのTimpstampで保存されているのでdayjs.jsライブラリを利用してフォーマットを行います。dayjsライブラリをnpmコマンドでインストールを行います。


 % npm install dayjs

dayjsライブラリを利用するためにWeather.jsファイルでdayjsのimportを行います。


import { useState, useEffect } from 'react';
import dayjs from 'dayjs';
function Weather() {
//略

2021-03-16のフォマットで表示させるためにformat(‘YYYY-MM-DD’)としています。その他のフォーマットについてはdayjsのドキュメントを参考にしてください。


dayjs(data.ts).format('YYYY-MM-DD')}

アイコン、気温、湿度が表示されるようにdataプロパティのweatherの配列の値に置き換えます。


<div className="p-4">
  <div className="bg-gradient-to-r from-blue-500 to-blue-300
                  w-96 h-56 m-auto rounded-xl shadow-2xl 
                  transform hover:scale-110 transition-transform
                  text-white relative">           
    <div className="w-full px-8 absolute top-6">
      <div className="flex justify-between">
        <div>
          <p className="font-light">City Name</p>
          <p className="text-lg font-medium tracking-widest">
            { data.name }
          </p>
        </div>
        <div>
          <img src={`${process.env.REACT_APP_OW_ICON_URL}/${data.weather[0].icon}.png`} 
                alt={data.weather[0].description}/>
        </div>
      </div>
      <div className="pt-2">
        <p className="font-light">Weather Condition</p>
        <p className="text-lg font-medium tracking-widest">
          { data.weather[0].main }
        </p>
      </div>
      <div className="pt-6 pr-6">
        <div className="flex justify-between">
          <div>
            <p className="font-light text-xs">
                Date
            </p>
            <p className="font-bold tracking-more-wider text-sm">
              { dayjs(data.ts).format('YYYY-MM-DD')}
            </p>
          </div>
          <div>
            <p className="font-light text-xs">
              Temprature
            </p>
            <p className="font-bold tracking-more-wider text-sm">
              {data.main.temp}°C
            </p>
          </div>
          <div>
            <p className="font-light text-xs">
              Humidity
            </p>
            <p className="font-bold tracking-more-wider text-sm">
              {data.main.humidity}%
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

ブラウザで確認すると天気の状態にあったアイコンも表示されます。

APIから取得したデータを表示
APIから取得したデータを表示

propsを利用して他の都市の天気取得

コンポーネント化しているので別の都市の天気も表示できるように直接入力していたTokyoの文字列をpropsから渡される変数に変更します。propsから渡す値は親コンポーネントであるApp.jsで設定します。

Weatherコンポーネントではpropsを受け取れるようにfunction Weahterの引数に{city_name}を設定しています。fetch関数の中でTokyoを{city.name}に置き換えています。またuseEffectの第2引数の配列にcity_nameを追加しています。

Weather関数に渡される変数は{city_name}ではなくpropsにすることも可能です。propsにした場合はcity_nameではなくprops.city_nameと設定する必要があります。

function Weather({city_name}) {

  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(()=>{
    fetch(`${process.env.REACT_APP_OW_API_URL}/weather/?q=${city_name}&APPID=${process.env.REACT_APP_OW_API_KEY}&units=metric`)
    .then(res => res.json())
    .then(result => {
      setData(result);
      setLoading(false);
    })
    .finally(() => {
      setLoading(false);
    });
  },[city_name])

App.jsからはWeatherコンポーネントタグにcity_name属性を追加してParisを設定します。この設定でpropsとしてcity_nameを渡すことができます。


<Weather city_name="Paris" />

city_nameに入った値を使ってOpenWeatherにアクセスを行いそのcity_nameに入った都市の天気を取得します。ブラウザ上には指定したParis(パリ)の天気が表示されます。天候はMIstで8.21度と東京に比較して寒いことがわかります。

パリの天気
パリの天気

複数のコンポーネントを利用

Weatherコンポーネントを作成したので2つの都市の天気を表示させることも簡単に行うことができます。App.jsでWeatherタグを1つ追加して2つとします。追加したWeatherタグのcity_name属性の値を別の都市名に変更するだけです。晴れの確率の高いLos Angelesを設定してみます。Weatherコンポーネントをwrapしているdiv要素には横幅に収まらない場合は自動で次の行になるようにflex-wrapを追加しています。


<div className="min-h-screen flex justify-center items-center flex-wrap">
  <Weather city_name="Paris" />
  <Weather city_name="Los Angeles" />

時差のため気温はかなり低めですがLos Angeles(ロサンゼルス)の天気は快晴であることが確認できます。

複数の都市の天気
複数の都市の天気

背景色を変更

背景色をブルーに設定していましたが都市名と同様にpropsを使って親コンポーネントから設定できるように変更します。propsで渡される変数にcolor_nameを追加します。


function Weather({city_name, color_name}) {

背景色はclassNameの中で設定を行っているのでcolor_nameの値を反映できるように以下のように更新します。


<div className={`bg-gradient-to-r from-${color_name}-500 to-${color_name}-300
                w-96 h-56 m-auto rounded-xl shadow-2xl 
                transform hover:scale-110 transition-transform
                text-white relative`}>

App.jsのWetherrタグにcolor_nameを追加し、色の設定を行います。設定できる色はカスタマイズで追加しない限りTailwind CSSのClassに登録されている色のみです。


<Weather city_name="Paris" color_name="red" />
<Weather city_name="Los Angeles" color_name="green" />
背景色を変更
背景色を変更

オブジェクトのcitiesを準備して4つの都市名とカラー名と設定し、map関数を利用して展開してWeatherコンポーネントを4つ作成します。


import Weather from "./Weather"
function App() {
  const cities = [
    {
      city_name: 'Tokyo',
      color_name: 'blue'
    },
    {
      city_name: 'London',
      color_name: 'yellow'
    },
    {
      city_name: 'Paris',
      color_name: 'green'
    }, 
    {
      city_name: 'Los Angeles',
      color_name: 'red'
    },
  ];

  return (
    <div className="min-h-screen flex justify-center items-center flex-wrap">
      { 
        cities.map((city,index) => 
        <Weather 
          key={index} 
          city_name={city.city_name} 
          color_name={city.color_name} 
        />)
      }
    </div>
  );
}

export default App;
4つの都市の天気を表示
4つの都市の天気を表示

色はpropsで渡しましたがOpenWeatherから返される天気の情報から色を設定することも可能です。またApp.jsに入力フォームを追加し、入力した都市の天気を表示させることも可能です。Reactのprops, useEffect, useStateを使うだけでさまざまなことを行うことができます。ぜひチャレンジしてみてください。