━目次━
Reactハンズオンその4です。
1から順番にやるのをオススメします。
React初心者のためのハンズオン その1[勉強方法とReactの基本]
React初心者のためのハンズオン その2[Propsとコンポーネント化]
React初心者のためのハンズオン その3[Stateでの状態管理]
React初心者のためのハンズオン その4[API実行と一覧表示]
coming soon…
さぁここまででReactの基本は理解できたでしょうか?
最初に比べてだいぶReactへの苦手意識もなくなってきたのではないかと思います。
今回のハンズオンでは、実際のアプリケーション開発でよくありそうな
「WebAPIでJSONデータを取得して、ループしながら一覧表示する」
というのをやってみようと思います!楽しみー!
Reactの世界へようこそ!チャオ React!!
完成品のイメージ
今回作るのは、ボタンを押下するとWEB上からJSONデータを取得してきて、一覧としてレンダリングするというものです。
表示される画面はこれまでと一緒ですが、システムっぽくなってきましたね。
コンポーネントの整理
では今回のハンズオンを始める前に少し画面を整理しましょう。
ここまでのコードを残しておきたい人は現在のindex.jsの内容を自分で退避するか、ログイン済の人は右上の「Fork」を押すことで現在の状態のまま別プロジェクトを始めることもできます。
まず以下のマーカーの箇所を削除します。
[index.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import React from "react"; import ReactDOM from "react-dom"; import ColorfulMsg from "./components/ColorfulMsg"; import CountButton from "./components/CountButton"; const App = () => { return ( <> <h2>Reactハンズオン!</h2> <ColorfulMsg color="blue">Reactは難しくないよー</ColorfulMsg> <ColorfulMsg color="green">Vueも難しくないよー</ColorfulMsg> <ColorfulMsg color="red">Angularは、、、</ColorfulMsg> <CountButton /> </> ); }; ReactDOM.render(<App />, document.getElementById("root")); |
削除後は以下の感じです。
[index.js]
1 2 3 4 5 6 7 8 9 10 11 12 |
import React from "react"; import ReactDOM from "react-dom"; const App = () => { return ( <> <h2>Reactハンズオン!</h2> </> ); }; ReactDOM.render(<App />, document.getElementById("root")); |
これで整理は完了です。
一覧表示用コンポーネントの作成
次にボタンを押したらメッセージ一覧を表示するコンポーネントの枠組みを新規作成しましょう。
作成するコンポ―ネントは「関数コンポーネント」でしょうか?「クラスコンポーネント」でしょうか?
「メッセージ一覧」を非表示の状態から表示にしたりという「状態」が必要なので「クラスコンポーネント」ですね!大正解!!
(※関数コンポーネントでStateを扱えるHooksは次のステップなので今は気にせずいきましょう)
前回までと同じ手順でcomponentsフォルダ配下に「MsgList.js」という名前で新規ファイルを作成し、以下のようにクラスコンポーネントの枠組みを作成しましょう。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import React from "react"; class MsgList extends React.Component { constructor(props) { super(props); this.state = {}; } render() { return <></>; } } export default MsgList; |
そして、index.jsで読み込んでおきます。まだ何もreturnしてないので何も表示されないです。
[index.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import React from "react"; import ReactDOM from "react-dom"; import MsgList from "./components/MsgList"; const App = () => { return ( <> <h2>Reactハンズオン!</h2> <MsgList /> </> ); }; ReactDOM.render(<App />, document.getElementById("root")); |
さぁ準備完了です!いよいよ一覧取得の内部処理を実装していきましょう!
データ取得用ボタンの設定
MsgListにデータ取得のきっかけとなるボタンを配置しましょう。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import React from "react"; class MsgList extends React.Component { constructor(props) { super(props); this.state = {}; } render() { return ( <> <button>メッセージ取得</button> </> ); } } export default MsgList; |
これまでやってきた内容でここは問題ないですね。
ではクリックイベントを設定していきます。
前回同様、まずはアラートが出ることの確認からしときましょう。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import React from "react"; class MsgList extends React.Component { constructor(props) { super(props); this.state = {}; } handleClick = () => { alert(); }; render() { return ( <> <button onClick={this.handleClick}>メッセージ取得</button> </> ); } } export default MsgList; |
さて問題なくアラートが表示されたでしょうか?
ふむふむ。なになに?タピオカが飲みたい? では一旦休憩して買ってきなさい。
axiosを使ってJSONデータを取得する
タイトルが何言っているのか分からない人もいるかもしれませんね。
それぞれ簡単に説明すると、
HTTP通信が簡単にできるJavaScriptライブラリ。APIを実行するときによく使われる。
JavaScript Object Notationの略。データのシンプルな表記法。WebAPIなどのデータのやりとりで最も使われているイメージ。
JSONは以下のように、キーと値のシンプルな構成のデータ表記法です。
[JSONの例]
1 2 3 4 |
{ "id" : 1, "name" : "じゃけぇ" } |
今回ハンズオンで使用するJSONデータは既にWEB上に配置しています。以下のリンクをクリックしてみてください。
https://api.myjson.com/bins/mt9wv
きれいにフォーマットすると、以下のようなデータになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "msgList": [ { "message": "Reactは難しくないよ~", "color": "blue" }, { "message": "Vueも難しくないよ~", "color": "green" }, { "message": "Angularは、、、", "color": "red" } ] } |
msgListという名前の配列の中に、messageとcolorの組み合わせがそれぞれ格納されています。
なにやらこの配列をループしながら処理すれば、色付きのメッセージが表示できそうな気がしますね。
では実際にaxiosを使って上記のJSONデータが取得できるか確かめてみましょう。
まずはaxiosというライブラリを使えるようにインストールします。
普通、ライブラリ等はnpmやyarnといったパッケージマネージャーのコマンドを使用してインストールしますが、CodeSandboxならGUIでインストール可能です。
左下の「Dependencies」を開いて、「Add Dependency」を押下します。
開いた画面の上部のテキストボックスに「axios」と入力すると、1番上にaxiosが表示されるのでクリック。
Dependenciesの配下にaxiosが追加されていればOKです!
これでaxiosが使えるようになりました。わざマシン並みに簡単ですね。
axiosを使う場合、使いたいファイルの中でimportする必要があるのでMagList.jsを編集しましょう。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import React from "react"; import axios from "axios"; class MsgList extends React.Component { constructor(props) { super(props); this.state = {}; } handleClick = () => { alert(); }; render() { return ( <> <button onClick={this.handleClick}>メッセージ取得</button> </> ); } } export default MsgList; |
axiosの基本的な構文は以下のようになっています。
axios.get(取得先のURL).then(成功時に実行される関数).catch(失敗時に実行される関数);
超絶シンプルですね。ボタンクリック時に先ほどのJSONのURLにアクセスするように書いていきます。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import React from "react"; import axios from "axios"; class MsgList extends React.Component { constructor(props) { super(props); this.state = {}; } handleClick = () => { axios .get("https://api.myjson.com/bins/mt9wv") .then(res => console.log(res)) .catch(err => alert(err)); }; render() { return ( <> <button onClick={this.handleClick}>メッセージ取得</button> </> ); } } export default MsgList; |
.get()の中にはアクセスするURL、.then()の中の関数は設定した引数に取得結果が入るようになっているのでそれをとりあえずコンソールに出力するように、.catch()の関数は引数にエラー情報が入るようになっているのでアラートで表示しています。
それでは「メッセージ取得」ボタンを押してみてください!
画面下部の「Console」の部分に何やら出力された感を感じますね。
Consoleを開いて、展開していくと、「data」の中に取得したJSON結果が格納されていることが確認できました。
このようにaxiosで取得したデータは、「data」の中に入ってきます。
やったぜぇぇえぇ!!
次はエラーを起こしてみよーう
URLの「9」の部分を「8」にして同様に実行すると、画像のようにエラーが表示されると思います。404なので「そんなURL存在しねーよ!」って怒られています。正しい動作ですね。
さぁ残るはコンポーネントへの取得結果の設定ですね。もう少しです。
map関数を使って一覧を表示する
Reactで一覧表示をする場合の典型パターンは、
Stateとして一覧表示用の配列変数をもっておき
その配列をJavaScriptのmap関数を使ってループ
ループ内でコンポーネントを出力
という流れです。
map関数はある配列を順番に処理し、新たな配列を生成する関数です。
例えば以下の例だと、元の配列をプラス1した配列を生成しています。
valの部分に元の配列の値が順番に入ってくるイメージです。
1 2 3 4 |
const arr1 = [1,3,5]; const arr2 = arr1.map(val => val + 1); console.log(arr2); // [2,4,6] |
この「順番に処理する」というのを利用するわけですね。
では書いていきます。まずは配列のStateを準備します。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import React from "react"; import axios from "axios"; class MsgList extends React.Component { constructor(props) { super(props); this.state = { msgList: [] }; } handleClick = () => { axios .get("https://api.myjson.com/bins/mt9wv") .then(res => console.log(res)) .catch(err => alert(err)); }; render() { return ( <> <button onClick={this.handleClick}>メッセージ取得</button> </> ); } } export default MsgList; |
次に、axiosでデータが取得できた場合setSateで配列を更新するようにします。
(StateのmsgListに、res.data.msgListを設定)
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import React from "react"; import axios from "axios"; class MsgList extends React.Component { constructor(props) { super(props); this.state = { msgList: [] }; } handleClick = () => { axios .get("https://api.myjson.com/bins/mt9wv") .then(res => this.setState({ msgList: res.data.msgList })) .catch(err => alert(err)); }; render() { return ( <> <button onClick={this.handleClick}>メッセージ取得</button> </> ); } } export default MsgList; |
そして最後に、map関数を使ってメッセージを出力します。以前作成したColorfulMsgコンポーネントを使いましょう。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import React from "react"; import axios from "axios"; import ColorfulMsg from "./ColorfulMsg"; class MsgList extends React.Component { constructor(props) { super(props); this.state = { msgList: [] }; } handleClick = () => { axios .get("https://api.myjson.com/bins/mt9wv") .then(res => this.setState({ msgList: res.data.msgList })) .catch(err => alert(err)); }; render() { return ( <> <button onClick={this.handleClick}>メッセージ取得</button> {this.state.msgList.map(val => ( <ColorfulMsg color={val.color}>{val.message}</ColorfulMsg> ))} </> ); } } export default MsgList; |
JavaScriptの関数を書くので{}で囲ってあげて、StateのmsgListをmap関数で順次処理します。
msgListの中には上のJSONデータで確認したように、「message」と「color」が入っているので、「msgList.message」「msgList.color」のようにデータを取得することができます。
なるほどの~ちょっと最初パニくるけど、順番にみたら分かるわ
やってることが理解できたらあとは慣れの問題だからいっぱい書いていくしかないね!
因みに、「return句がごちゃごちゃして見辛い!」という人は、一度変数に格納しておくのもありです。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import React from "react"; import axios from "axios"; import ColorfulMsg from "./ColorfulMsg"; class MsgList extends React.Component { constructor(props) { super(props); this.state = { msgList: [] }; } handleClick = () => { axios .get("https://api.myjson.com/bins/mt9wv") .then(res => this.setState({ msgList: res.data.msgList })) .catch(err => alert(err)); }; render() { const colorfulMsgList = this.state.msgList.map(val => ( <ColorfulMsg color={val.color}>{val.message}</ColorfulMsg> )); return ( <> <button onClick={this.handleClick}>メッセージ取得</button> {colorfulMsgList} </> ); } } export default MsgList; |
やっていることはほとんど同じですね。ここは好みの問題ですかね。
画面の再読み込みをして、「メッセージ取得」ボタンを押してみましょう!
おぉぉぉぉぉおー!!できたー!!
ちょっと待ったぁぁぁぁ~!!
またかー!
Consoleに何やら警告が出ていませんか?
Warning: Each child in a list should have a unique “key” prop.
何を言っているかと言うと、
「リスト要素にはkeyを設定しろ言うとるやろがい!しばくぞ」
らしいです。
このように、map関数などを使って一覧表示する要素にはkeyを設定する必要があります。
以前のハンズオンで、「Reactは仮想DOMと比較して変更がある部分のみ再レンダリングする」と言いましたが、この「比較」のために必要だからです。
なのでkeyには一意になる値を設定してあげる必要があります。
今回はJSONデータの中にID項目などはないので、messageを設定してみたいと思います。
[MsgList.js]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import React from "react"; import axios from "axios"; import ColorfulMsg from "./ColorfulMsg"; class MsgList extends React.Component { constructor(props) { super(props); this.state = { msgList: [] }; } handleClick = () => { axios .get("https://api.myjson.com/bins/mt9wv") .then(res => this.setState({ msgList: res.data.msgList })) .catch(err => alert(err)); }; render() { return ( <> <button onClick={this.handleClick}>メッセージ取得</button> {this.state.msgList.map(val => ( <ColorfulMsg key={val.message} color={val.color}> {val.message} </ColorfulMsg> ))} </> ); } } export default MsgList; |
これで、メッセージを取得しても警告はでなくなったと思います!お疲れ様です!完成です!!
さいごに
今回でかなりステップアップしましたね!
イベントのハンズオンも、時間の関係で前回のその3までしかできなかったので初公開です。
尚、このハンズオンのソースはGitHubで公開しています。
https://github.com/freelance-jak/react-handson_4_axiosmap
次のステップとしては、
ライフサイクル
画面遷移
Redux
Hooks
あたりだと思うので、また追い追いこのブログで紹介したいと思います~!
もし「分かり易い!」と感じたら是非のボタンからシェアしてReactの輪を拡げて頂けたらと思います!
↓その5へ↓
【近日そのうち公開】
それでは!また!!
人気の記事だけ集めたので是非覗いていってください^^
厳選!目的別にオススメ記事を紹介-あなたの欲しい情報がここに-