
React.js チュートリアル[超入門] #03 Propsを使ってみる
前回のレッスンでは、Componentを一から自分で作ってみました。今回は、propsについて学びます。
このレッスンの目標
・Propsを理解する
・Title.jsにテキストをpropsとして渡してみる
・inline-styleを渡してみる
・event handlerを渡してみる
・props.childrenを使う
前回までの作業フォルダーは、僕のgithubから確認/ダウンロードできます。
1. Propsを理解する
Propsとは、Properties(直訳すると所有物とか資産とか言う意味)の略称です。僕は、propsをそれぞれのcomponentが持つ情報のようなものだと理解しています。propsは、文字だったり、functionだったり、styleだったりその時々によって違います。
しかし何故、componentが情報を持つ必要があるのでしょう。前回のレッスンで作成したTitle.jsの例を使って考えてみます。Title.js に直接、「Hello World 2.0」 と書き込みました。componentの最大の強みは再利用可能であることです。このままだと、「Hello World 2.0」をたくさん表示することはできますが、「Hello World 3.0」だったり、「こんにちは世界2.0」と表示したいときに、新しくcomponentを作り直す必要が出てきます。再利用性が極めて低い状態です。
では、Title.jsにpropsとして、<h1>タグに挿入されるべき情報を渡せたらどうでしょう?そうすると一つのcomponentを使っているのに、様々なシチュエーションで利用できることができるようになります。再利用性が高い状態です。これこそがpropsを使う主な理由の一つです。
2. Title.jsにテキストをpropsとして渡してみる
Propsのイメージが掴めたところで、どうすればTitle.jsの文字情報をpropsとして渡せるか一緒にコードを書いていきましょう。
まず、Title.jsを以下のように編集します。これでpropsのtitle情報をh2タグで受け取る準備ができました。
// Title.js
const Title = (props) => {
return(
<div>
<h2>{props.title}</h2>
</div>
)
}
次に、App.jsの<Title />を以下のように編集します。これで"Hello World 3.0"という文字情報がtitleというpropsに渡されます。
// App.js
<Title title="Hello World 3.0"/>
下の写真のようにブラウザーで確認できたら成功です。ここで覚えておきたいのは、今回指定したtitleというpropsの情報名は自由に設定できるということです。これを例えば、「title」から「titleText」だったり「versionStatement」に変更しても機能します。シンプルでわかりやすく、使い回しのしやすい名前にするのが好ましいです。
3. styleを渡してみる
文字列をpropsとしてcomponentに渡すことができたので、今度はstyleを渡して見ましょう。styleの詳細は、次回のレッスンで学ぶ予定なので、まず一番単純なinline-styling(JSXに直接書き込んで行く方法)で試してみます。
まず、propsなしでTitle.jsを装飾してみましょう。波括弧が二つ必要だという点にも注目してください。
// Title.js
<h2 style={{color: '#56D6FB'}}>{props.title}</h2>
そうすると、下のように文字が水色になったと思います。
今度は、このTitle.jsのinline-stylingをpropsを使って実現してみます。propsの名前はストレートにtitleStyleにしました。
// Title.js
<h2 style={props.titleStyle}>{props.title}</h2>
次は親componentである、App.jsを編集していきます。titleStyle propsにinline-stylingの情報を渡してください。今回は文字の色をオレンジにしました。
// App.js
<Title title="Hello World 3.0" titleStyle={{color: 'orange'}}/>
下のようになっていると成功です。
4. Event handlerを渡してみる
今度はevent handlerを渡してみます。Event handlerとは、ある出来事が起きたら発生するイベント処理のことを言います。例えば、ボタンをクリックしたときの処理だったりも、このevent handlerを使うことで、実装できます。今回は、「Upgrade」という文字をクリックすると、「Hello World 3.0」が、「Hello World 4.0」 に変わり、ボタンが消えるというイベントを実装しましょう。
実装の流れ
1. 「upgrade」ボタンを設置して、「upgrade」ボタンと「Hello World」のそれぞれにidをつける。
2. onClick イベントをpropsとして受け取れるよう、Title.jsを変更する。
3. App-headerの高さをコメントアウトする(デフォルトで固定されていて、要素が隠れてしまう為)。
4. Event handlerを定義する。
5. Event handlerをpropsに渡す。
まずTitle.jsで「upgrade」ボタンを設置して、要素にidをつけていきます。idをつけるのはボタンをクリックしたときに、その特定のタグを取得しやすくする為です。ついでに、onClickで発動してほしいevent handlerをpropsで受け取れるよう、pタグに、onClick={props.onClick}と追記します。
タグの情報が増えてきたので、改行し始めました。見やすくする為です。
// Title.js
const Title = (props) => {
return(
<div className="titleSection">
<h2
style={props.titleStyle}
id="versionStatement"
>{props.title}</h2>
<p
onClick={props.onClick}
id="upgradeButton"
>Upgrade</p>
</div>
)
}
結果
何故かボタンが隠れてしまいました。デフォルトのcssファイルでApp-headerクラスの高さが150pxに固定されているからです。この部分のcssをコメントアウトします。App.cssを開いてください。
// App.css
.App-header {
background-color: #222;
/* height: 150px; */
padding: 20px;
color: white;
}
そうすると、下のようにボタンが上手く表示されるはずです。
いい感じですね。では次に、Event handlerをApp.jsで定義します。基本的に、イベントハンドラーのコードはclass クラス名 extends Component と render()メソッドの間に記述していきます。
Event handlerの名前に規則はありませんが、わかりやすい名前であり、同じcompoenent内の他のevent handlerと重ならなければ、問題ないです。
class App extends Component {
// イベントハンドラー
onClickHandler = () => {
// 「Hello World」のh2タグをここで取得
let title = document.getElementById('versionStatement');
// 「upgrade」のpタグをここで取得
let upgradeButton = document.getElementById('upgradeButton');
// 取得したh2タグのテキストを変更
title.textContent = "Hello World 4.0";
// 取得したpタグを非表示にする。
upgradeButton.style.display = "none";
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
// イベントハンドラーをここでpropsに渡す。
<Title
title="Hello World 3.0"
titleStyle={{color: 'orange'}}
onClick={this.onClickHandler}
/>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
中身は通常のjavascriptなので詳しく説明しません。コード内のコメントを参考にしてください。定義が完了したら、<Title /> componentにevent handlerを渡します。ここでキーとなるのが、component内で定義したevent handlerは、this.EVENT HANDLERの名前でアクセスすることができます。
もう一つ付け加えるとすると、ここでthis.onClickHander()のように余計な()を足さないことです。javascriptに慣れている人だと、functionの後に()をつける習慣があると思いますが、()をつけてしまうと、ブラウザーがcomponentを読み込んだ時点で、実行されてしまいます。
下のように動いたら成功です。
5. props.childrenを使う
これまで、文字列、スタイル、イベント処理の情報をpropsでcomponentに渡してきましたが、propsは、そういった細かい情報だけでなく、JSX自体を渡すこともできます。例えば、Title.jsのh2タグHello World 4.0の数字部分をspanで囲みたい場合。下記のように書き換えるだけで実現できます。
// Title.js
<h2
style={props.titleStyle}
id="versionStatement"
>
{props.children}
</h2>
// App.js
<Title
title="Hello World 3.0"
titleStyle={{color: 'orange'}}
onClick={this.onClickHandler}
>
Hello World <span id="versionCounter" style={{borderBottom: '1px solid orange'}}>3.0</span>
</Title>
props.childrenは、「親componentの中で参照されたcomponentタグにあるJSXを全部挿入していください」という便利なトリックです。これを使うと、containerやboxなど他のcomponentの入れ物になるような要素を、効率的に作ることができます。
下のように数字部分の下にアンダーラインが表示されたら成功です。
この部分はおまけです。Upgradeをクリックすると数字だけ変わってほしいので、onCLickHandlerを以下のように編集します。これで、span内の数字のみ変更されるようになりました。
// App.js
onClickHandler = () => {
let title = document.getElementById('versionCounter');
let upgradeButton = document.getElementById('upgradeButton');
title.textContent = "4.0";
upgradeButton.style.display = "none";
}
まとめ
今回のレッスンはここまです。これでPropsの基礎はおえることができました。
#03 Propsを使ってみる
✔︎ Propsを理解する
✔︎ Title.jsにテキストをpropsとして渡してみる
✔︎ inline-styleを渡してみる
✔︎ event handlerを渡してみる
✔︎ props.childrenを使う
初めて触れる方は、なかなか謎な内容だったと思います。これからもたくさん練習する機会があるので、安心してください!!
質問があればいつでも、コメント欄やTwitterで受け付けてます。