兵どもが、夢のあとさき

JavaScript 系の言語に興味を惹かれ、まったりと更新しております

Reactって何だー(ソフトウェア開発編 その1)

photo in Kyoto city

 さて、"Hello World!!" の表示は行うことができたので、次に簡単なプログラムを作成してみましょう。お題は、友人のいる地域の天気予報一覧です。
私は、とあるスマホゲームをやっておりオフ会等を行ってきた結果(最近はコロナの影響でできませんが…)全国に友人を増やすことができました。最近(2022/07/11現在)は気温も高くなり、コロナの他にも熱中症にも気を使うことも多く、その話題でチャットが盛り上がったりします。
 そこで、今回は全国各地にいる友人の地域の天気予報(現在の気温、湿度等も含む)を一覧にして表示するプログラムを作成することにしました。

 

 天気予報の情報は、気象庁JSON 形式で提供していますので、こちらを使用させていただきます。(気象庁の情報を利用するためには利用規約があります。使用する場合にはこちらを十分留意してください。)

 

 

 早速とりかかるとします。今回のプロジェクト名は "weather" 、構築環境は VSCode を使用します。まず、コマンドプロンプト/ターミナルでプロジェクトを作成します。
 

例によって数分かかります。今日は暑いのでアイスコーヒーを作って飲んで待ってます

完了しました。では次に VSCode で本プロジェクトを開きます。

 

 

本プロジェクトの流れは、下記のようになります。

 

(1) ユーザがボタンを押す

(2) 気象庁のサイトから気象情報を JSON 形式で取得

(3) 予め設定した地域の情報を選択

(4) HTML 形式で出力

となります。いたってシンプルですね。

 

ここで一点言い訳弁明を。react ではコンポーネントと呼ばれる小さな部品を組み上げてソフトウェアを作成することが推奨されています。これは、前回も述べたように小さな部品を構成することにより、変更点が生じた場合最小限の労力で、修正することができるからです。しかし、ここでは手を抜いて前回の "Hello World!!" で使用した、App() コンポーネントにすべて入れ込むことにしました。初学者は細かいことを考えるよりガンガン手を動かして、ソフトウェアをガンガン作成していきましょう!

 

と言うことで、App() コンポーネントに必要なソースを書いていきます。

App.js を開きます。デフォルトでは下記の様になっています。

ユーザがボタンを押す

 ユーザがボタンを押すためには、そのボタンを表示させなければなりません。では、ボタンを表示させます。20行目に下記を記載して下さい。

        <div><button> みんなの天気予報 </button></div>

 これは JSX でも何でもなく、単なる HTML ですね。しかし、とりあえずボタンらしいものは表記されるようになりました。

このボタンは押しても何も起こりません。それは当然です。ボタンを押したときのイベント処理に対するソースを何も記載していませんから。

 では次に、その処理のソースを記載しましょう。ただし、JSON の取得部分のソースもまだですので、何か別の変化が起こる様にしましょう。例えば、よくあるポップアップにしましょうか。

 

一応の説明をしておくと、JSX は return 文で DOM(HTML)を返します。従って、return 文の中に変数定義を記述することはできません。

例えば、JSX では、変数の定義に const を使用しますが、

 const weatherData = 'みんなの天気予報'

を return 文の中に記載してしまうと(20行目)、

 

下記の結果になります。

ですので、JSX で変数定義等を行う場合には、return 文の外に記載する必要があります。書き換えてみましょう。

6行目の return 文の外に、変数を定義しました。そして13行目に {weatherData} と記述しました。結果は?

の様に、6行目で定義した weatherData という変数の内容が、13行目の {weatherData} によって正常に表記されています。

 ※重要なことを記載していませんでした。JSX で定義した変数を、return 文内で使用する場合には、{  } で括って下さい。そうでないと変数名そのままが表記されてしまいます。

 前置きが長くなりました。それでは、ボタンクリックイベントを作成しましょう。

 イベントが発生した時の関数を作成しましょう。ポップアップでいいので、alert 文を使用します。前述のとおり、return 文の外(今回は前)で定義します。ついでに <button> タグにも、その関数を呼び出す様に JSX を記載します。

8~10、26行目に注目してください。

 関数定義 const buttonAlert = () => {  は独特の表記ですが、今は雰囲気だけ味わっておいて下さい。そのうち () 内に props とか入り始めますから。

8~10行 は関数定義、26行は button タグに、その関数を呼び出す様に記述しました。しつこい様ですが、return 内で JSX の関数名や変数名を使用する場合には、{  } で括ることを忘れないで下さい。b

では実行。ボタンをクリック!

あれ? 何ですかこの [object Object] とは?

ググるとー。JSON.stringify(変数名) で内容が取得できるらしい。では、

おおー。要するに連想配列(react だと何て言うんでしょう? => 連想配列でいいらしい。javascript だから当然ですか)だから key と data に分ければ良いようです。まあここは本質では無いのでこのまま放置します。(JSON.stringify(変数名) 関数はブラウザ依存なのであまり使用しない方が良いですね。今回は chrome を使用)
とりあえず、ボタンイベントが完成したので次へ進みます。

 

気象庁のサイトから気象情報を JSON 形式で取得

 とりあえず、気象庁のサイトをブラウザで叩いてみるとこうなります。

JSON データの羅列が取得できます。でも凄まじい量ですね。これを毎度毎度取得するのもリソースの無駄ですし、何といっても気象庁のサイトに負担をかけてしまいます。そこで、まず東京のみの情報を取得してみたいと思います。

https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json

これをブラウザで叩いてみてください。

ほうほう、東京都の情報が得られました。しかも、天気予報や気温などの情報も含まれているではないですか。

これを JSX から取得するには、Axios というライブラリを使用します。それでは実際に実装してみます。

Axios を使用するには、まず axios ライブラリを import する必要があります。下記の3行目。

すると、

エラーとなります。どうやら、Axios ライブラリはデフォルトでは実装されていないようです。ここで取る手段は2つ。npm を使用してライブラリをインポートするか、CDNを使用して外部からライブラリを引き込むかの二択です。Axios 自体は軽いライブラリですので(94k程度)npm を使用してインポートします。

下記を実行します。

 npm install axios(npm i axios という省略形もあります)

完了しました。

CDN を使用する場合には、/pubic/index.html の <body> タグ内に

<script type="text/babel">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" />
 

の様に 記載すればOKです。

 

さて、では Axios を実装していきましょう。

3行目で、Axios ライブラリをインポートしています。

9~14行目が、気象庁のデータにアクセスし、console.log で結果を出力する Req() 関数定義となります。axios.get() 関数でシンプルに HTTP の GET メソッドで気象庁JSON 情報を取得します。

※ console.log はデバッガに結果を出力するメソッドなので、実行前に console.clear で内容をクリアしています

18行目で Req() を呼び出します。

さて結果は?

ボタンを押しても何も変化は無いと思います。前述のとおり、console.log は画面上ではなく、デバッガに結果を出力するメソッドすので画面上には出力されません。ここで、デバッガを立ち上げます。ctrl + shift + I (i です、愛)すると、

デバッガが立ち上がります。デバッガの、上部にある console タブをクリックして下さい。

status は、HTTP のレスポンス状態を示しています。200 ですから正常に取得できていますね。では次に、取得したデータを見てみましょう。「▶ {data: ~ の ▶ をクリック」=> 「▶ {request: ~ の ▶ をクリック」=> 「」。responseText という項目がありますので、カーソルをそこにフォーカスすると、東京都全域の情報がテキスト表示されます。

これは、つまり気象庁が提供している JSON データを response 変数に格納されたことを意味します。デバッガでは、その内容を確認できた訳ですね。

response 変数に JSON データが格納されたことは確認できましたが、次にこの内容を展開して UI 上に表示する必要があります。それでは response 変数の展開を行っていきます。

 

<余談>

 コンポーネントの呼び出し方ですが、これまで App() の様に関数であるかのような表記を使ってきました。しかし jacascript では様々な呼び出し方があり、例えば下記の様な表記方法もあります。18行目を参照してください。

呼び出し方は様々です。本来は統一した方がデバッグも行いやすいと考えますが、人の書いたコードをメンテしたりする際に、色々な手法を知っておかないと困ることもありますので、「あーこんな表記方法もあるんだな」程度で良いと思いますので学んでおいて損は無いと思います。他にも import と require の関係など枚挙にいとまがありません。

</余談>

予め設定した地域の情報を選択

 まずは単純に気象庁JSON データにどの様な情報が含まれているのか、それをブラウザ上でわかりやすい表記を行えるようにしましょう。と、その前に VSCode 上で成形して見やすくしてみましょう。再度、気象庁のサイトをブラウザで叩いてみてください。JSON データがずらりと表記されます。これをすべてコピーしてください(全選択 ctrl + a して ctrl + c)。ここで VSCode へ戻り、「新規ファイル」=> 「新しいテキスト ファイル」(ctrl + n でもOKです)から新規ファイルを開きます。

テキスト内に、「言語の選択」とありますので、そこをクリック

「言語モードの選択」という入力画面が表示されますので、JSON と入力。

「{ } Json (json)」をクリック。

この画面に戻りますので、先ほどコピーした JSON データを貼り付け(ctrl + v)。

こんな感じで、一行にペーストされました。ここで、shift + alt + f と打ってください。

この様に可読性の良いフォーマットで JSON データが表示されます。ちなみに、このデータの頭は(テキストの適当な部分をクリックして、)、

 この様に北から情報が取得できることが分かると思います。"centers" タグは中央管区の情報を包括(のちほど別のタグも出没します)を表し、"name" 及び "enName" はそのエリア名、"officeName" は各エリアの管区気象台の日本語表記、"childlen" はその名の通り、そのエリアがどこの地域を統括しているかということ(ここでは単なる数字表記ですが)が何となく分かると思います。

fig.1

 さてここで、行数を示す箇所にカーソルを移動させると、下向きの鏃の様なマークが表記されます。2行目もそうですね。下向きということは、ここではすべての情報が展開されていることを意味しています。ここで、2行目の鏃をクリックしてみてください。

fig.2

"centers" タグが折りたたまり、139行目から始まる "offices" タグ情報が表記されました。ここで注視していただきたいのが、fig.1(唐突に図番を入れました)と、fig.2 の比較です。fig.2 では140行目にタグの無い、"011000" 表記があります。そして fig.1 では、8行目に同様に "011000" と記載されています。これはつまり、"centers" の "children" である "011000" の情報が、"offices" に書かれていると言うことを表してみます。つまり、

の配下に、

        "011000": {
            "name": "宗谷地方",
            "enName": "Soya",
            "officeName": "稚内地方気象台",
            "parent": "010100",
            "children": [
                "011000"
            ]
        },

この様に、宗谷地方が含まれていることが分かると思います*1

 

 と、ここまで来ましたが実はこのデータは各地域(行政区とは異なるかな?)のコード(さきほど確認した "011000" のことですね)を確認するために取得したものです。実は天気予報の JSON 情報は別にありまして、

 https://www.jma.go.jp/bosai/forecast/data/forecast/xxxxxx.json(xxxxxx が先ほど取得した地域コード)が実際の天気予報の情報となります。それでは、せっかく宗谷地方のコードが判明しましたので、そちらの天気予報を見てみましょう。

 https://www.jma.go.jp/bosai/forecast/data/forecast/011000.json

をブラウザで叩いてみてください。

 これを先ほどの手順で VSCode に張り付けて成形すると

 この様に、宗谷地方の天気予報らしき情報を得ることができました。これは使えそうですね。(東京の情報を取得するつもりが、宗谷地方になっていますけれど…)

 

 かなり話が外れてしまいましたが、それでは Axois を実装して宗谷地方の情報を取得してみましょう。

11行目から、16行目までが変更点です。実行し、デバッガを立ち上げます。そして適当に展開してみると、

 今日(2022/07/23現在)の宗谷地方は少し天気が悪そうです。
 さて、それでは各個別の情報を取得していきましょう。JSON入れ子になっており、多段化されていることが多いです。気象台のデータもかなり入り組んでいますね。そこで必要な要素のみを取得してみましょう。まず、地域コード "011000" の地名を取得します。下記の要領で展開して(一部展開を戻しました)、name が地域名となりますが相当深い位置にありますね。これを手繰るのは大変なので、name へカーソルを持っていき、右クリックすると下記のメニューが表示されます。ここで「Copy property path」を選択。パスがクリップボードに読み込まれます。これは後ほど使用します。

さて、VSCode に戻ります。

18行目に alert(response) と書き込み、実行してみると、

この様になります。これは以前も発生した現象ですね。つまり、内容が Object なので、そのままでは表示されないわけです。

そこで、コードを下記の様に書き換えて下さい。



18行目の「data[0].timeSeries[0].areas[0].area.name」とは何ぞや、と思われたかと。実はこれが先ほどクリップボードに読み込んでおいた、JSONname のパスに相当します。この様に深いネストでも、デバッガの「Copy property path」から読み取り、貼り付け(ctrl + v)で簡単に対応することができるわけです。実行してみると、

 この様に、地域コード "011000" の地名を取得することができました。天気予報も同時に表示したければ、下記の様に + で連結すれば表記されます。

alert に出力ばかりしても意味がありませんから、画面遷移を使って表示させてみます。

25行目、id 'root' 全体を書き換えました。

一応表示されました。ただ、画面遷移するのは気持ち悪いのでもう少し手を入れます。App.js の46 ~ 48行目に新たに、<div id='weather'>を差し込みます。

そして、

obj 変数内のコンテキストを、先ほどの id = 'weather' に差し込みます。さて結果は?

上図の様に、画面遷移無しに宗谷地方の気象情報が表示されました(2022/07/24現在)。

 

実はこのソースかなり適当に書かれています。悪いお手本の様なソースですね。JSX ライクな書き方ではありませんし、Axiosも正しく使用されていません(エラーハンドリング等)。それでは、次のページでは Axios の正しい使い方や、JSX ライクな記述法、最終目標である友人たちのエリアの天気予報を完成させたいと思っております。では。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

私が参照した、遅延勉強法の動画です。これ、私知らず知らずのうちにやってました。

www.youtube.com

 

*1:JSON に関しては、こちらのサイトの方が非常に分かり易く書かれていますので、ぜひ一度チェックなさってください