条件付きレンダリング
コンポーネントは、多くの場合、異なる条件に応じて異なるものを表示する必要があります。Reactでは、if文、&&、および? :演算子などのJavaScript構文を使用してJSXを条件付きでレンダリングできます。
学習内容
- 条件に応じて異なるJSXを返す方法
- JSXの一部を条件付きで含めたり除外したりする方法
- Reactコードベースでよく見かける条件付き構文のショートカット
JSXを条件付きで返す
複数のItemをレンダリングするPackingListコンポーネントがあるとします。これらのアイテムは梱包済みか未梱包かでマークできます:
一部のItemコンポーネントでは、isPackedプロップがfalseではなくtrueに設定されていることに注意してください。isPacked={true}の場合、梱包済みアイテムにチェックマーク(✅)を追加したいとします。
これは次のようにif/else文として記述できます:
もしisPackedプロップがtrueの場合、このコードは異なるJSXツリーを返します。この変更により、一部のアイテムの末尾にチェックマークが表示されます:
どちらのケースで何が返されるかを編集して、結果がどのように変化するか確認してみてください!
JavaScriptのifとreturn文を使って分岐ロジックを作成していることに注目してください。Reactでは、条件などの制御フローはJavaScriptによって処理されます。
nullを使用して何も返さない条件付きレンダリング
状況によっては、何もレンダリングしたくない場合があります。例えば、梱包済みアイテムをまったく表示したくないとします。コンポーネントは何かを返す必要があります。この場合、nullを返すことができます:
もしisPackedがtrueの場合、コンポーネントは何も返さず、nullとなります。それ以外の場合は、レンダリングするためのJSXを返します。
実際には、コンポーネントからnullを返すことは一般的ではありません。なぜなら、それをレンダリングしようとしている開発者を驚かせる可能性があるからです。より一般的には、親コンポーネントのJSX内でコンポーネントを条件付きで含めたり除外したりします。その方法は次の通りです!
JSXを条件付きで含める
前の例では、コンポーネントによってどのJSXツリーが返されるかを制御しました。レンダリング出力にいくつかの重複があることにすでに気づいているかもしれません:
は、次のものと非常に似ています:
どちらの条件分岐も<li className="item">...</li>を返します:
この重複は有害ではありませんが、コードの保守性を低下させる可能性があります。classNameを変更したい場合はどうでしょうか?コード内の2箇所で変更する必要があります!このような状況では、条件付きで少しのJSXを含めることで、コードをよりにすることができます。DRY(重複しない)
条件(三項)演算子 (? :)
JavaScriptには、条件式を記述するための簡潔な構文があります —条件演算子または「三項演算子」です。
この代わりに:
このように書けます:
これは、「もしisPackedが真なら(?)、name + ' ✅'をレンダリングし、そうでなければ(:)、nameをレンダリングする」と読むことができます。
次に、完了したアイテムのテキストを別のHTMLタグ、例えば<del>で取り消し線を引くためにラップしたいとします。改行や括弧をさらに追加することで、各ケースにより多くのJSXをネストしやすくすることができます:
このスタイルは単純な条件には適していますが、適度に使用してください。コンポーネントがネストされた条件付きマークアップで煩雑になる場合は、子コンポーネントを抽出して整理することを検討してください。Reactでは、マークアップはコードの一部であるため、変数や関数などのツールを使用して複雑な式を整理できます。
論理AND演算子 (&&)
もう一つよく使われるショートカットは、JavaScriptの論理AND(&&)演算子です。Reactコンポーネント内では、条件が真の場合にのみJSXをレンダリングし、それ以外の場合は何もレンダリングしない場合によく使われます。&&を使用すると、isPackedがtrueの場合にのみチェックマークを条件付きでレンダリングできます:
これは、「もしisPackedなら(&&)、チェックマークをレンダリングし、そうでなければ何もレンダリングしない」と読むことができます。
実際の動作は次のとおりです:
JavaScriptの&&式は、左側(条件)がtrueの場合、右側の値(この場合はチェックマーク)を返します。しかし、条件がfalseの場合、式全体はfalseになります。Reactはfalseを、nullやundefinedと同様にJSXツリーの「穴」と見なし、その場所には何もレンダリングしません。
落とし穴
&&の左側に数字を置かないでください。
条件をテストするために、JavaScriptは左側を自動的にブール値に変換します。しかし、左側が0の場合、式全体がその値(0)になり、Reactは何もレンダリングせずに0をレンダリングしてしまいます。
例えば、messageCount && <p>New messages</p>のようなコードを書くのはよくある間違いです。messageCountが0のときに何もレンダリングしないと考えるのは簡単ですが、実際には0自体がレンダリングされます!
これを修正するには、左側をブール値にします:messageCount > 0 && <p>New messages</p>。
JSXを変数に条件付きで割り当てる
ショートカットが素直なコードの記述を妨げる場合は、if文と変数を使用してみてください。letで定義された変数は再代入できるので、最初に表示したいデフォルトのコンテンツ(名前)を提供します:
JSX式をif文で条件付きにitemContentに再代入するには、isPackedがtrueの場合に以下のようにします:
中括弧は「JavaScriptへの窓」を開きます。中括弧を使って変数を返されるJSXツリーに埋め込み、先に計算した式をJSX内にネストします:
このスタイルは最も冗長ですが、最も柔軟でもあります。実際の動作は以下の通りです:
前と同様に、これはテキストだけでなく任意のJSXでも機能します:
JavaScriptに慣れていない場合、このような様々なスタイルは最初は圧倒されるかもしれません。しかし、これらのスタイルを学ぶことは、Reactコンポーネントだけでなく、あらゆるJavaScriptコードを読み書きするのに役立ちます!まずは好みのスタイルを選び、他のスタイルの動作を忘れた場合はこのリファレンスを再度参照してください。
まとめ
- Reactでは、分岐ロジックはJavaScriptで制御します。
- 条件付きでJSX式を返すには、
if文を使用します。 - 条件付きでJSXを変数に保存し、中括弧を使って他のJSX内に含めることができます。
- JSXでは、
{cond ? <A /> : <B />}は「condが真なら<A />をレンダリングし、そうでなければ<B />をレンダリングする」という意味です。 - JSXでは、
{cond && <A />}は「condが真なら<A />をレンダリングし、そうでなければ何もレンダリングしない」という意味です。 - これらのショートカットは一般的ですが、プレーンな
if文を好む場合はそれを使用する必要はありません。
いくつかの課題を試してみましょう
Challenge 1 of 3:? : を使用して未完了アイテムにアイコンを表示する#
条件演算子 (cond ? a : b) を使用して、isPacked が true でない場合に ❌ をレンダリングしてください。
