Reactの続きです。前回ではJSXで関数の入れ子をやってみました。今回からは制御構造に入って行きます。まずは分岐から。JSXはif文をそのまま書くとエラーになるという衝撃の事実から、回避方法をご紹介。論理演算子(&&
、!
)、三項演算子(?
、:
)で書く方法も。それでは行きましょう!
【目次】
- ReactのJSXではif文が書けない!?
- JSXにif文を直書きしてみる(結果、エラー。。)
- if文を即時関数に入れる
- if文をJSX外部の関数として書く
- 論理演算子&&で書く
- 三項演算子?:で書く
- 最後に
前回の記事
※参考:【React】JSXの中に別の関数のJSXを読み込む(入れ子状態) - クモのようにコツコツと
Reactを習得するためにやったことまとめ
qiita.com
ReactのJSXではif文が書けない!?
React習得、掌田さんの「React.js & Next.js超入門」を参考に進めていて、制御構造(分岐、反復)に進んだ。
- 作者:津耶乃, 掌田
- 発売日: 2019/03/08
- メディア: 単行本
ここで疑問に思ったのがReactの制御構造としてif文(分岐)やfor文(反復)を使わない書き方を紹介していること。
調べるてみるとなんと、Reactが採用しているJSXではif文やfor文が書けないらしい!?
if statements and for loops are not expressions in JavaScript, so they can’t be used in JSX directly.
「ifステートメントとforループはJavaScriptの式ではないため、JSXで直接使用することはできません。」
「JavaScriptの式ではない」え?いや、そ、そうなのかい?JSの式だと思うのだが。。
まあ確かにC言語やJavaなども同じ書き方なので「JSの式です!」とは言い切れないのかも知れないが、それがJSXで使えない理由になるのがよくわからない…。
JSXにif文を直書きしてみる(結果、エラー。。)
本当かどうか、確かめてみる。JSXの中にif文を直接書いてみた。
See the Pen React 10 if-ng by イイダリョウ (@i_ryo) on CodePen.
結果としては、JSXが動いてない。「読み込み中」となっていると言うことはそう言うことだ。本当だ…。
ちなみに書いたコードはこちら。
HTMLコード
<section> <h1>楽しい楽しいお店</h1> <div class="text">読み込み中…</div> </section>
.text
には初期値として「読み込み中…」と言うテキストを入れており、このタグをReactで書き換えている。このテキストが表示されている=Reactが動いていないと言うことだ。
JSコード
//DOM取得 const text = document.querySelector('.text'); //JSXに埋め込む値 const h2Text = "楽しい楽しいお店にようこそ!"; const pText = "(18歳以上の方がお楽しみいただけます)"; const okMsg = "ようこそ!ご入場ください。"; const ngMsg = "お引き取りください。"; const age = 35; //JSXの中身 const elm = ( <section className="h2_elem"> <h2>{ h2Text }</h2> <p>{ pText }</p> { if ( age >= 18 ) { <p>{ okMsg }</p> } else { <p>{ ngMsg }</p> } } </section> ); //レンダリング ReactDOM.render(elm, text);
- 変数
text
で.text
のDOMを取得 - 変数
h2Text
はh2
タグに表示したいテキスト - 変数
pText
はp
タグに表示したいテキスト - 変数
okMsg
は条件分岐で条件がOKなときに表示したいテキスト - 変数
ngMsg
は条件分岐で条件がNGなときに表示したいテキスト - 変数
age
は条件として入れる値35
- 変数
elm
でJSXを設定
h2
タグにh2Text
を読み込み
p
タグにpText
を読み込み
if文age
が18以上であればokMsg
を表示
さもなくばngMsg
を表示 ReactDOM.render
でelm
をレンダリングしてtext
に返す
「楽しい楽しいお店」の入り口で年齢制限を設けている(R18)。
age
の値が35
なのでokMsg
の「ようこそ!ご入場ください。」が表示されることを期待していたが、Reactが丸ごと動いてない。
if文を即時関数に入れる
これを回避する方法として、まずir文を即時関数に入れる方法がある。
※参考:React JSX の中で if で分岐させたい - かもメモ
即時関数はこのような書き方。
//即時関数 (()=> { //処理 })();
これを使うメリットはスコープ汚染を防ぐこと。即時関数の中に書いた変数名は外の変数名と被っても干渉しない。
※参考:JavaScriptで即時関数を使う理由 - Qiita
以前、Tone.jsでも変数i
を即時関数に入れて解決したことがある。
※参考:【Tone.js】3コード楽器のコードをリファクタリング(ループとイベントと即時関数) - クモのようにコツコツと
これを使うとJSXの中でもif文が動くようだ。やってみる。
See the Pen React 11 if-ok by イイダリョウ (@i_ryo) on CodePen.
おお!期待通りに表示された!
35歳なので「ようこそ!ご入場ください。」と表示されてる!Reactでif文、動きまぁす♪
JSコード
//JSXの中身 const elm = ( <section className="h2_elem"> <h2>{ h2Text }</h2> <p>{ pText }</p> {(() => { if ( age >= 18 ) { return <p>{ okMsg }</p> } else { return <p>{ ngMsg }</p> } })()} </section> );
- if文を即時関数で囲う。
- JSXは
return
で返す
ただ、即時関数自体もブロック{ }
で囲っているので、かなりカッコが重複して直感的じゃないねw
※2020/03/04追記
なお、if文の中のJSXにreturn
を付けないとJSXは表示されなかった!
See the Pen React 11 if-ng2 by イイダリョウ (@i_ryo) on CodePen.
p
タグまでのJSXは反映されたが、その下のif文から先が反映されていない。
{(() => { if ( age >= 18 ) { <p>{ okMsg }</p> } else { <p>{ ngMsg }</p> } })()}
return
によってJSコードとJSXのhtmlタグの境界を識別できるようだ。
if文をJSX外部の関数として書く
前回の記事でやったように、外部に関数を書いて、それをJSXの中に組み込むのもいけそうなのでやってみる。
※参考:【React】JSXの中に別の関数のJSXを読み込む(入れ子状態) - クモのようにコツコツと
See the Pen React 12 if-ok by イイダリョウ (@i_ryo) on CodePen.
おお、これもまた動いた!
JSコード
const msg = () => { if ( age >= 18 ) { return <p>{ okMsg }</p> } else { return <p>{ ngMsg }</p> } } //JSXの中身 const elm = ( <section className="h2_elem"> <h2>{ h2Text }</h2> <p>{ pText }</p> { msg() } </section> );
- 変数
msg
に無名関数を代入してif文の処理をかく p
タグの後にmsg()
を読み込む
JSXの中に書かなければ問題ないと言うことか。
論理演算子&&で書く
掌田さんの本ではif文以外の方法が紹介されていて、1つ目は論理演算子&&
を使う方法。
論理演算子は「AかつB(&&
)」「AまたはB(||
)」「A以外!
」など。よく、if文やfor文の条件式の中で複数の条件を指定するときに使ったりする。
これを使ってif文のような条件分岐をできるんだなー。やってみよう。
See the Pen React 13 Branch-1 by イイダリョウ (@i_ryo) on CodePen.
おお、動いた!
JSコード
//JSXの中身 const elm = ( <section className="h2_elem"> <h2>{ h2Text }</h2> <p>{ pText }</p> { age >= 18 && <p>{ okMsg }</p> } { !age >= 18 && <p>{ ngMsg }</p> } </section> );
elm
のp
タグの次に論理演算子で式を書いているage
が18以上がtrueならばp
タグにokMsg
を表示age
が18以上がtrueじゃなければ(!
)p
タグにngMsg
を表示
&&
の前が条件となり、結果がtrueの時だけ値を返す。else
が無いif
単独の条件分岐(それ以外は何もしない)に使われる。
条件の頭に!
を付けることで、trueじゃない場合、と言う条件になる。こういう書き方は普段しないので新鮮!
if文は使えないけど演算子は普通に使えるため、JSXの中で条件分岐を設定できる、と言うわけか。
三項演算子?:で書く
もう一つ、三項演算子でも書くことができる。
三項演算子はVue.jsでTodoリストを作ったときに書いた。
※参考:【Vue.js】localStorageと連携したTodoリストを読み解く(JS編-3) - クモのようにコツコツと
このような書き方。
条件 ? trueの場合の処理 : falseの場合の処理
※参考:条件 (三項) 演算子 - JavaScript | MDN
なお、分岐が2択ではない場合も、分岐を繰り返し書くことによって指定ができるようだ。
※参考:このくらいまでならjsで三項演算子使ってもいいよね、っていうパターン(個人的に) - Qiita
やってみた。
See the Pen React 14 Branch-2 by イイダリョウ (@i_ryo) on CodePen.
やた!これも動いた。
JSコード
//JSXの中身 const elm = ( <section className="h2_elem"> <h2>{ h2Text }</h2> <p>{ pText }</p> { age >= 18 ? <p>{ okMsg }</p> : <p>{ ngMsg }</p> } </section> );
p
タグの後に三項演算子を書いているage
が18
以上か(?
)、trueならp
タグにokMsg
を表示
falseならp
タグにngMsg
を表示
この書き方の方が先程の論理演算子(&&
、!
)よりも重複がなくてスマート。
ただ、スマートすぎて?
や:
の一文字を見逃す可能性もありそうw
最後に
と言うことでJSXで条件分岐をするいくつかの方法を試してみました。どの方法でも結果は同じなので、お好みということになるかと思います。個人的にはこのように感じました。
方法 | 備考 |
---|---|
即時関数にif文 | JSXの構造が膨らむので直感的じゃない?閉じカッコが重なっている部分も間違えそう。 |
外部の関数にif文 | それぞれの関数の中がシンプルなので見通しは良さそう。 |
論理演算子(&& 、! ) |
! を使った分岐は重複するのでelse がないif 単独の分岐に良さそう |
三項演算子(? 、: ) |
処理の行数が少ない簡単な条件分岐ならこれで済ませても良さそう。見逃し注意! |
次回は反復をやってみます。こちらもJSXの中にfor文を直接書くことが出来なそうです。それではまた!
Reactを習得するためにやったことまとめ
qiita.com