React公式ドキュメントを読む18 if文以外でレンダリングし分ける

前回からの続きですが、このページだけ読んでも分かる内容になっています。 今回読むReact公式ドキュメントは「条件付きレンダー」ページの後半です。

Reactで条件によってレンダリング内容を変えたい場合、状況によってはif文を使わずにより短い書き方が選択できるかもしれません。このページでは、if文以外でレンダリングし分ける場合のコード書き方を紹介します。

JSXのなかに中括弧 {} で式を埋め込む

JavaScriptの論理演算子の && を使った例

中括弧 {} で囲むことで、JSXのなかに任意の式を埋め込むことができます。以下のコードは、中括弧 {} のなかにJavaScriptの論理演算子の && を使ったコードを埋め込んでいます。

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;

  /*
  以下の {unreadMessages.length > 0 && <h2>…</h2>} の部分では、
  論理演算子の && を使って評価が true かどうかをしています。
  評価が true なら && 以降の要素が出力されます。
  */
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          未読メッセージが {unreadMessages.length} 件あります。
        </h2>
      }
    </div>
  );
}

const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  <Mailbox unreadMessages={messages} />,
  document.getElementById('root')
);

上記のサンプルソースをHTMLファイルにしたものが以下です。

https://programming-world.net/sample/react_doc/conditional-rendering2-1.html

上記コードでは、 中括弧 {} で埋め込んだ部分のコードで、論理演算子の && を使って評価が true かどうかをしています。評価が true なら && 以降の「 <h2>未読メッセージが {unreadMessages.length} 件あります。</h2> 」の部分が出力されます。

もし評価が false となる場合には、<h2>…</h2>の部分は出力されません。 これは、JavaScriptで論理演算子の&&では、片方が false でもう片方が式なら全体がfalseと評価されるためです。

一方で、片方が true でもう片方が式なら全体は式として評価されます。その結果、&& 以降の「 <h2>未読メッセージが {unreadMessages.length} 件あります。</h2> 」の部分が出力されます。

尚、論理演算子の AND(&&) は、演算対象の両方が true なら true が返り、そうでなければ false が返ります。論理演算子には他に、OR (||) と NOT (!)があります。適切に使い分けることで、様々な条件判定ができます。

  • AND(&&) … 演算対象の両方が true ならtrue を返し、そうでなければfalse を返します。
  • OR (||) … 演算対象のどちらかが true ならtrue を返し、両方とも false の場合はfalse を返します。
  • NOT (!) … 演算対象が true なら false を返し、そうでなければ true を返します。

JavaScriptの条件演算子の condition ? true : false を使った例

以下のコードは、JavaScriptの条件演算子の condition ? true : false を使った例です。中括弧 {} のなかに condition ? true : false を使ったコードを埋め込んでいます。

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      現在 <b>{isLoggedIn ? 'ログイン' : 'ログアウト'}</b> 中です。
    </div>
  );
}

上記のコードでは、{isLoggedIn ? ‘ログイン’ : ‘ログアウト’} の部分で表示内容を振り分けています。 isLoggedIn の値が true なら「ログイン」、falseなら「ログアウト」と出力されます。

上記のコードにおける true / false の評価部分は比較的短いですが、 condition ? true : false 条件演算子は、以下のようなより長い式を評価する際にも使えます。

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? (
        <LogoutButton onClick={this.handleLogoutClick} />
      ) : (
        <LoginButton onClick={this.handleLoginClick} />
      )}
    </div>
  );
}

上記のコードでは、 isLoggedIn の値が true なら<LogoutButton />、falseなら<LoginButton />を呼び出しています。

このJavaScriptの条件演算子の condition ? true : false を使った書き方は、 true / false の評価部分が長くなるほどコードが読みにくくなるかもしれません。

もし条件が複雑になってしまう場合には、コンポーネントとして抽出してif文で条件分岐した方が良い場合もあるでしょう。状況に応じて適切な書き方を選択してください。

ちなみに、条件演算子は三項演算子とも呼ばれます。 一般的には、三項演算子という呼び方のほうがなじみがあるかもしれません。三項演算子(条件演算子)では、条件式を評価して true なら式1を返し、false1なら式2を返します。以下は、 三項演算子(条件演算子)の書式です。

条件式 ? 式1 : 式2

以下は、三項演算子(条件演算子) の使用例です。

var age = 26;
var beverage = (age >= 21) ? "ビール" : "ジュース";
console.log(beverage); // "ビール"

この 三項演算子(条件演算子) の使用例の引用元はこちらです。

コンポーネントの表示/非表示を切り替える

以下のコードは、ボタンが押されたかどうかで、特定のコンポーネントの表示/非表示を切り替えるプログラムになっています。

function WarningBanner(props) {
  //レンダー出力の代わりに null を返すと非表示になります
  if (!props.warn) {
    return null;
  }

  return (
    <div className="warning">
      ご注意!
    </div>
  );
}

// Pageコンポーネント
class Page extends React.Component {
  // コンストラクタ
  constructor(props) {
    super(props);

    // showWarning の値を true にして初期化
    this.state = {showWarning: true}

    // メソッドをバインド
    this.handleToggleClick = this.handleToggleClick.bind(this);
  }

  // クラスメソッド
  handleToggleClick() {
    this.setState(prevState => ({
      showWarning: !prevState.showWarning
    }));
  }
  
  /*
  以下の部分では、条件演算子を使用しています。
  this.state.showWarning が true なら [非表示にする] ボタンを、
  false なら[表示する] ボタンをレンダリングします。
  */
  render() {
    return (
      <div>
        <WarningBanner warn={this.state.showWarning} />
        <button onClick={this.handleToggleClick}>
          {this.state.showWarning ? '非表示にする' : '表示する'}
        </button>
      </div>
    );
  }
}

// Pageコンポーネントを呼び出します
ReactDOM.render(
  <Page />,
  document.getElementById('root')
);

上記のサンプルソースをHTMLファイルにしたものが以下です。

https://programming-world.net/sample/react_doc/conditional-rendering2-2.html

上記コードは、warn というプロパティの値が true かどうかによって、「ご注意!」の部分の表示と非表示が切り替わるプログラムとなっています。

Reactではレンダー出力の代わりに null を返すと、そのコンポーネントは非表示になります。上記コードでは、warnプロパティの値が true ではない場合には、if (!props.warn) { ~ } の条件に合致してreturn null されます。

ボタンをレンダリングする部分では、条件演算子を使用しています。this.state.showWarning が true なら [非表示にする] ボタンをレンダリングして、falseなら[表示する] ボタンをレンダリングします。

次回へ続きます。