コンポーネントは、多くの場合、異なる条件に応じて異なるものを表示する必要があります。Reactでは、if
文、&&
、および? :
演算子のようなJavaScript構文を使用して、JSXを条件付きでレンダリングできます。
学習内容
- 条件に応じて異なるJSXを返す方法
- JSXの一部を条件付きで含めたり除外したりする方法
- Reactコードベースで遭遇する一般的な条件付き構文のショートカット
JSXの条件付き返し
いくつかのItem
をレンダリングするPackingList
コンポーネントがあるとします。これらのアイテムは、梱包済みとしてマークすることもできます。
function Item({ name, isPacked }) { return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
いくつかのItem
コンポーネントのisPacked
プロパティがfalse
ではなくtrue
に設定されていることに注意してください。isPacked={true}
の場合、梱包済みのアイテムにチェックマーク(✅)を追加したいと考えています。
これをif
/else
文として記述することができます。
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
isPacked
プロパティがtrue
の場合、このコードは異なるJSXツリーを返します。 この変更により、一部のアイテムの最後にチェックマークが表示されます。
function Item({ name, isPacked }) { if (isPacked) { return <li className="item">{name} ✅</li>; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
どちらの場合にも返されるものを編集して、結果がどのように変わるかを確認してみてください!
JavaScriptのif
文とreturn
文を使って分岐ロジックを作成していることに注目してください。Reactでは、制御フロー(条件など)はJavaScriptによって処理されます。
null
による条件付きの何も返さない
状況によっては、何もレンダリングしたくない場合もあります。たとえば、梱包済みのアイテムをまったく表示したくない場合です。コンポーネントは何らかのものを返す必要があります。この場合、null
を返すことができます。
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
isPacked
がtrueの場合、コンポーネントは何も、つまりnull
を返します。そうでない場合は、レンダリングするJSXを返します。
function Item({ name, isPacked }) { if (isPacked) { return null; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
実際には、コンポーネントからnull
を返すことは一般的ではありません。レンダリングしようとする開発者を驚かせる可能性があるためです。多くの場合、親コンポーネントのJSXでコンポーネントを条件付きで含めたり除外したりします。その方法は次のとおりです!
JSXの条件付きインクルード
前の例では、コンポーネントから返されるJSXツリー(存在する場合)を制御しました。レンダリング出力に重複があることに既に気づいているかもしれません。
<li className="item">{name} ✅</li>
は、
<li className="item">{name}</li>
どちらの条件分岐も<li className="item">...</li>
を返します。
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
この重複は有害ではありませんが、コードの保守性を難しくする可能性があります。className
を変更したい場合はどうでしょうか?コードの2箇所で変更する必要があります!このような状況では、JSXを条件付きで含めることで、コードをよりDRY (Don't Repeat Yourself)にすることができます。
条件演算子(三項演算子)(? :
)
JavaScriptには、条件式を記述するための簡潔な構文があります — 条件演算子 または「三項演算子」です。
これの代わりに
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
これを記述できます。
return (
<li className="item">
{isPacked ? name + ' ✅' : name}
</li>
);
isPacked
がtrueの場合(?
)、name + ' ✅'
をレンダリングし、そうでない場合(:
)、name
をレンダリングする、という意味です。
詳細
オブジェクト指向プログラミングのバックグラウンドをお持ちの方であれば、上記の2つの例は微妙に異なるだろうと考えるかもしれません。その理由は、いずれかの例が<li>
の2つの異なる「インスタンス」を作成する可能性があるためです。しかし、JSX要素は内部状態を持たず、実際のDOMノードではないため、「インスタンス」ではありません。それらは、設計図のような軽量な記述です。したがって、これらの2つの例は、実際には完全に同等です。状態の保持とリセットでは、この仕組みについて詳しく説明しています。
次に、完了したアイテムのテキストを<del>
などの別のHTMLタグで囲みたいとします。より多くのJSXを各ケースにネストしやすくするために、さらに改行と括弧を追加できます。
function Item({ name, isPacked }) { return ( <li className="item"> {isPacked ? ( <del> {name + ' ✅'} </del> ) : ( name )} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
このスタイルは単純な条件には適していますが、適度に使用してください。コンポーネントがネストされた条件付きマークアップが多すぎて混乱する場合は、子コンポーネントを抽出することで整理することを検討してください。Reactでは、マークアップはコードの一部であるため、変数や関数などのツールを使用して複雑な式を整理できます。
論理AND演算子 (&&
)
もう一つのよく使われるショートカットは、JavaScriptの論理AND演算子(&&
)です。Reactコンポーネント内では、条件がtrueの場合にいくつかのJSXをレンダリングする場合、またはそうでない場合は何もレンダリングしない場合によく使用されます。&&
を使用すると、isPacked
がtrue
の場合にのみチェックマークを条件付きでレンダリングできます。
return (
<li className="item">
{name} {isPacked && '✅'}
</li>
);
isPacked
がtrueの場合(&&
)、チェックマークをレンダリングし、そうでない場合は何もレンダリングしない、という意味です。
これが動作している様子です。
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✅'} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
JavaScriptの&&式は、左辺(条件)がtrue
の場合、右辺の値(この場合はチェックマーク)を返します。しかし、条件がfalse
の場合、式全体がfalse
になります。Reactはfalse
をJSXツリーの「穴」と見なし、null
やundefined
と同様に、その場所に何もレンダリングしません。
JSXを条件付きで変数に代入する
ショートカットが通常のコード記述の邪魔になる場合は、if
文と変数を使用してみましょう。let
で定義された変数は再代入できるので、まず表示したいデフォルトの内容、つまり変数名を指定します。
let itemContent = name;
isPacked
がtrue
の場合、if
文を使用してJSX式をitemContent
に再代入します。
if (isPacked) {
itemContent = name + " ✅";
}
中括弧は「JavaScriptへの窓」を開きます。 計算済みの式をJSX内にネストし、中括弧で変数を返されるJSXツリーに埋め込みます。
<li className="item">
{itemContent}
</li>
このスタイルは最も冗長ですが、最も柔軟性も高いです。動作例を示します。
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = name + " ✅"; } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
前述と同様に、これはテキストだけでなく、任意のJSXにも有効です。
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = ( <del> {name + " ✅"} </del> ); } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
JavaScriptに慣れていない場合、これらのスタイルのバリエーションは最初は圧倒的に感じるかもしれません。しかし、これらを学ぶことで、あらゆるJavaScriptコード(Reactコンポーネントだけではありません!)の読み書きに役立ちます。まずは好きなスタイルを選び、他のスタイルの書き方を忘れた場合は、このリファレンスを再度参照してください。
まとめ
- Reactでは、JavaScriptを使用して分岐ロジックを制御します。
if
文を使用して、JSX式を条件付きで返すことができます。- 中括弧を使用して、JSXを条件付きで変数に保存し、他のJSXの中に含めることができます。
- JSXにおいて、
{cond ? <A /> : <B />}
は「cond
が真の場合、<A />
をレンダリングし、そうでない場合は<B />
をレンダリングする」という意味です。 - JSXにおいて、
{cond && <A />}
は「cond
が真の場合、<A />
をレンダリングし、そうでない場合は何もレンダリングしない」という意味です。 - ショートカットは一般的ですが、通常の
if
を好む場合は使用しなくても構いません。
課題 1の 3: ? :
を使用して、未完了のアイテムにアイコンを表示します
isPacked
がtrue
でない場合、条件演算子(cond ? a : b
)を使用して❌をレンダリングします。
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✅'} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }