ReactでのJSXで条件付き三項演算子を使用する
ReactのJSXの中で、Reactの開発者が条件を設定する方法は複数あります。
if/else文やswitch文も使えますが、第三の方法として三項演算子がございます。
この記事では、Reactで三項演算子を使用する方法について学習します。
Vanilla.JSでの三項演算子の基礎は下記で解説しております。
軽く三項演算子のおさらいをしときましょう。
三項演算子
条件付き三項演算子は、3つのオペランド(値や変数)を取る唯一のJavaScript演算子となります。
この演算子は、値を返すif文のショートカットつまり代替えとしてよく使用されます。
条件を設定し、true
またはfalse
に基づいて特定の値を返す非常に簡単な方法です。
それによって、動的クラスを設定したり、動的インラインスタイルを適用したり、文字列の値を条件付きでレンダリングしたりできます。
Reactでの三項演算子
React.jsの三項演算子は、JavaScriptでの動作と同じように動作致します。
error ? "true(真)" : "false(偽)"
三項演算子の助けを借りて、すべてがtrue
とfalse
の条件に依存する1つの条件に基づいてコンテンツを表示できます。
・ 条件の後に?(疑問符)
・ 条件がtrueの場合に実行する式
・ 条件がfalseの場合に実行する式
コンテンツを条件付きで配置できます。
ReactはJavaScriptライブラリであるため、ReactではプレーンなJSを使用可能です。
ただし、ReactではJSX(JSとHTMLのブレンド)も使用します。
そのため、Reactで三項演算子を使用して条件付きレンダリングを行うには、その手順に従います。
JSX内に記述する
ユーザーのリストを表示と非表示のリストコンポーネントを作成します。
レンダリングするリストをusersという変数として定義します。
const users = [ {name: "Taro"}, {name: "Hanako"}, {name: "Michael"} ] const showList = true;
showList
という条件をtrueに設定にします。
それでは、条件付き三項演算子でReactでリストを表示していきます。
const App = () => { const users = [ {name: "Taro" }, {name: "Hanako"}, {name: "Michael"}, ] const showList = true; return ( <div> { showList ? ( <div> <h2>users List</h2> <ul> {users.map((user, index) => <li key={index}>{user.name}</li> )} </ul> </div> ) : ( // 評価がfalseの場合 <p>ユーザーは存在しません。</p> ) } </div> ); };
JSX内部で三項演算子を使用する場合、中括弧内{ }
に記述していきます。
{ showList ? (<div>true</div>) : (<p>false</p>)}
三項演算子を使用すると、追加の構文を使用せずに単一の要素を返すことができますが、複数のコンポーネントを返すには、括弧( )とフラグメントタグの両方が必要であることに注意してください。
See the Pen React 三項演算子 リストの表示 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
このアプローチは、返される2つの異なるコンポーネントがあまり長くない場合によく使用されます。
返されるコードブロックの1つが何行にもわたって長い場合は読みにくく、理解するのが難しくなる可能性があります。
他の例でも見てみましょう。
ユーザーリストのオブジェクトを子のコンポーネントへ渡して、条件付きでそれぞれ表示します。
// 親コンポーネント const App = () => { const users = {name: "Taro", last_login_at: "Hanako" } return ( <div> <Greeting users={users} /> </div> ); }
// 子のコンポーネント const Greeting = ({users}) => { return ( <div> { name === null ? <h1>Hi</h1> : ( <div> <h1>Hello {users.name}</h1> <h2>最後にログインした人{users.last_login_at}</h2> </div> ) } </div> ); }
users
オブジェクトが提供されている場合、より詳細な挨拶を条件付きでレンダリングします。
三項演算子を使用すると、このように追加の構文を使用せずに単一の要素を返すことができます。
See the Pen React 三項演算子 例② by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
ここからさらに、少し複雑になりますが、以前の記事でPropsの渡し方チュートリアルで子のコンポーネントから親のコンポーネントへデータを渡す方法を解説しました。
それを活用しましょう、フックを使用し、子からコールバックとして親へデータを渡して、条件付き三項演算子の条件に基づいてボタンをクリックしたらユーザーの名前を表示します。
まず下記は親コンポーネントになります。
const App = () => { const [childData, setChildData] = useState({ name: 'Taro', last_login_at: '不明' }); const sendData = (data) => { setChildData(data); }; return ( <div> <Greeting sendData={sendData} /> { name === null ? <h1>Hi {childData.name}</h1> : ( <div> <h1>Hello</h1> <h2>最後にログインした人: {childData.last_login_at} </h2> </div> ) } </div> ) }
useStateフックに渡されたオブジェクトの初期値は片方のプロパティの値は、条件三項演算子の条件で表示されないのでTaro
とします。
もう一つのプロパティの値は、初期値では不明とします。
ボタンをクリックしたら、他の名前を表示させます。
それでは、子のコンポーネントで新しくオブジェクトを再定義します。
子に渡されたPropsはuseStateの2番目の引数である関数です、他の値であるTaro
は変更する必要がないのでスプレッド演算子を使用して、オブジェクトの一部の値を更新(コピー)します。
// 子コンポーネント const Greeting = ({sendData}) => { //再定義 const users = { last_login_at: '不明' }; const ClickHandler = () => { //一部の値を更新 sendData({...users, last_login_at: 'Hanako'}); } return ( <div> <button onClick={ClickHandler}> 最終ログインの確認 </button> </div> ); }
See the Pen React 三項演算子 コールバック 子から親へデータを渡す by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
条件付き三項演算子の条件に基づいて、ボタンクリック時に状態が更新され、最終ログインした人の名前である、Hanako
が表示されます。
Propsとして子コンポーネントに関数を渡し、コールバックで親コンポーネントに情報を渡している流れです。
親コンポーネントの状態を実行および更新しています。
このような、方法あるんだなと思って頂ければ幸いです。
子から親へデータを渡す詳しい使用方法は、下記を参照下さい。
Reactでのネストされた三項演算子
Reactのネストされた条件付きレンダリングは可能だと思いますか?
はい、可能となります。
ですが、一部のJavaScriptコードは理解しにくい場合があるため、読みやすくすることは絶対に必要です。
ネストされた三項演算子より、if文のが読みやすいと私は思っております。
経験豊富な開発者がネストされた三項演算子を使用しているの見かける時が多々ありますが、あまり良い習慣とは言えません。
三項式をネストすると、コードが理解しにくくなる可能性があります。
デバッグしたり、コードに何かしらの機能を追加したりするとき、ネストされた三項演算子を見た時は、おぞましさを感じます。
非常に単純な場合を除いて、ネストされた三項演算子の使用はお勧めできません。
プロジェクトでESLintを使用する場合、no-nested-ternary規則である、ルールを使用してネストされた三項式を禁止にする事も可能となります。
ESLint v0.2.0で導入されたルールとなります。
もしくは、コンポーネントを複数のコンポーネントとして分割し、各コンポーネントはネストされていない独自の条件付きレンダリングを処理するようにして下さい。
当ブログの記事では、React初心者様には三項演算子によるネストの解説は致しませんのでご了承下さい。
学ばれたい方は他の教材やドキュメントを参照下さい。
単純なネストでしたら、例を示しておきます。
return ( <div> {isNotAvailable ? <p>リストは表示できません</p> : (isEmpty ? <p>リストの中が空です</p> : <div>{list.map(item => <Item item={item} />)}</div> ) } </div>
See the Pen React 三項演算子 ネスト by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
上記のデモでは、ネストされた複数の子コンポーネントつまりプロップドリルによって表示していますが
フックでの条件付きやループまたは変更された順序でレンダリングする場合、ほとんどの場合ではフックを 1レベル下の子コンポーネントに移動させますのでご注意下さい。
ネストも可能という事は覚えておいて下さい。
論理積演算子
論理積AND (&&)演算子を使用して、いくつかの条件に応じてさまざまなUIをレンダリングできます。
つまり、要素をレンダリングするか、何もレンダリングしないかのどちらかをレンダリングしたい場合がよくあります。
論理積でも、条件を三項演算子のようにインライン化できるようにする必要があります。
Reactで条件付き三項演算子を使用した場合、この論理積による条件付きレンダリングは頻繁に使用されます。
要素を返すのではなく、何も返さない次の読み込みインジケータコンポーネントを確認下さい。
const LoadingIndicator = ({ isLoading }) => { return ( <div> {isLoading ? <p>Loading...</p> : null} )</div> }
JSXで条件をインライン化可能です。
三項演算子でのnullは引用符で囲まないようにしてください。
// ✖︎ {isLoading !== 1 ? "Hello" : "null"} // ○ {isLoading !== 1 ? "Hello" : null}
単純にそのままnull
を使用します。
ただし、null
を返す必要がない別の方法があります。
これは、nullを返す条件をより簡潔にするのに役立ちます。
条件が真の場合、論理積( && )演算子の後の式が出力され、条件がfalse
の場合、Reactは式を無視してスキップします。
const App = () => { const isLoading = true; return ( <div> {!isLoading && "Hello world!"} {isLoading && "Loading..."} </div> ); }
これは、何も返さないかJSX内の要素を返したい場合の方法となります。
See the Pen React 論理積 条件 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
下記では、useStateフックを使用した条件付きの切り替えとなります。
const App = () => { const [isLoading, setisLoading] = useState(true) return ( <div> <button type="button" onClick={() => setisLoading(!isLoading)}>ボタン</button> {!isLoading && "Hello world!"} {isLoading && "Loading..."} </div> ); }
See the Pen React フック 論理積 条件 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
上記の例では、論理否定で反転させている事に注意して下さい。
これらは短絡評価とも呼ばれ、三項演算子よりもさらに簡潔になります。
インラインスタイルでの三項演算子
インラインスタイルとして三項演算子を使用する場合、スタイルオブジェクトに特定のプロパティを設定する際に、条件付きでチェックします。
const App = () => { const [count, setCount] = useState(0); return ( <div> <h2 style={count > 0 ? {backgroundColor: 'black', color: 'red'} : {backgroundColor: 'blue', color: 'white'} }>Count: {count} </h2> <button onClick={() => setCount(current => current + 1)}> Increment </button> </div> ); };
See the Pen React インラインスタイル三項演算子 by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
上記では、値が同じ条件によって決定される複数のプロパティがある場合、三項演算子を使用しプロパティと値のオブジェクト全体を返すことが可能となっています。
styleのPropsに値を設定する際に、条件付きでチェックします。
その場合、中括弧{ }
を2つ使用します。
<h2 style={変数 ? {cssプロパティ} : {cssプロパティ} }> Count: {count} </h2>
外側のセットは、Reactに対して評価されるべき式があることを示します。
中括弧の内側のセットは、CSSプロパティと値のオブジェクトとなります。
変数count
に0
より大きな値が格納されているかどうかをチェックし、格納されている場合はbackgroundColor
プロパティにBlack
そしてcolor
にredを、そうでない場合はbackgroundColor
がBlueでcolor
をWhiteを設定します。
また、クリックするたびにcolor
とbackgroundColor
を交互に切り替えたい、その場合はクリックイベントのたびにカラーを切り替える必要があります。
colorIndex
とbackgroundColorIndex
を交互に切り替えるように useState フックを使用して管理し、三項演算子の中で配列から対応する色を選択するようにします。
その方法の例を下記に示します。
const App = () => { const [count, setCount] = useState(0); const [colorIndex, setColorIndex] = useState(0); const [backgroundColorIndex, setBackgroundColorIndex] = useState(0); const colors = ['white', 'red']; const backgroundColors = ['blue', 'black']; const style = { backgroundColor: backgroundColors[backgroundColorIndex], color: colors[colorIndex], }; const handleClick = () => { setCount((current) => current + 1); setColorIndex((current) => (current + 1) % colors.length); setBackgroundColorIndex((current) => (current + 1) % backgroundColors.length); }; return ( <div> <h2 style={style}>Count: {count}</h2> <button onClick={handleClick}>Increment</button> {colorIndex === backgroundColorIndex ? ( <p style={{ color: 'red' }}>色は同じにできません。</p> ) : null} {colorIndex !== backgroundColorIndex ? ( <p style={{ color: 'green' }}>色も違います。</p> ) : null} </div> ); };
See the Pen React 三項演算子 色の切り替え by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
上記のコードでは、条件に基づいて2つの<p>
要素をレンダリングしています。
1つの<p>
要素は、背景色と文字色が同じ場合に表示されます。
もう1つの<p>
要素は、背景色と文字色が異なる場合に表示されます。
これにより、色の組み合わせが有効かどうかをユーザーに知らせることができます。
下記では、三項演算子を使用しない場合です。
const App = () => { const [count, setCount] = useState(0); const [colorIndex, setColorIndex] = useState(0); const [backgroundColorIndex, setBackgroundColorIndex] = useState(0); const colors = ['white', 'red']; const backgroundColors = ['blue', 'black']; const style = { backgroundColor: backgroundColors[backgroundColorIndex], color: colors[colorIndex], }; const handleClick = () => { setCount((current) => current + 1); setColorIndex((current) => (current + 1) % colors.length); setBackgroundColorIndex((current) => (current + 1) % backgroundColors.length); }; return ( <div> <h2 style={style}>Count: {count}</h2> <button onClick={handleClick}>Increment</button> </div> ); };
上記のようにしても、クリックするたびにcolor
およびbackgroundColor
の色が交互に切り替わるようになっています。
See the Pen React インラインスタイル三項演算子 ② by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
プロパティと値のオブジェクトを個別で返すのか、オブジェクト全体なのか、どのアプローチを選択するかは個人の好みの問題となっております。
最後に
Reactで条件付きレンダリングを実現する複数の方法はございます、if文やSwitch文を使用した条件付きレンダリングやJavaScriptのオブジェクトをEnumと共に使用して、キーと値のペアのマップとして使用するとオブジェクトを列挙型として使用可能となります。
各アプローチには、それぞれ独自の利点があります。
ユースケースで必要になるのはほとんどがif文かもしれませんが、JSXコード内部で条件文を処理する場合は、三項演算子を使用するのが最善の策です。
これは、条件をチェックし結果に応じて適切なコンポーネントを『返す』
ことによって行われます。
本日は以上となります。
最後まで読んで頂きありがとうございます。
この記事が気に入ったらブックマークし、他の方に共有してください。