開発者ドキュメント

Reactアプリケーションで条件付きレンダリングを実装する7つの方法

序章

動的でReactとの高度なインタラクティブ性を備えたシングルページアプリケーション(SPA)を構築できます。 これを可能にする1つの機能は、条件付きレンダリングです。

条件付きレンダリングは、条件がtrueまたはfalseの場合に、さまざまなユーザーインターフェイス(UI)マークアップをレンダリングする機能を表す用語です。 Reactでは、条件に基づいてさまざまな要素やコンポーネントをレンダリングできます。 この概念は、次のシナリオでよく適用されます。

この記事では、Reactアプリケーションで条件付きレンダリングを実装する7つの方法を検討します。

前提条件

このチュートリアルを完了するには、次のものが必要です。

このチュートリアルは、Node v15.6.0、npm v7.4.0、およびreactv17.0.1で検証されました。

サンプルプロジェクトの設定

ユーザーがログインする必要があるアプリケーションについて考えてみます。 ユーザーがログアウトすると、ログインボタンが表示されます。 ユーザーがログインしている場合は、ログアウトボタンが表示されます。

create-react-appを使用してReactアプリを生成することから始めます。

  1. npx create-react-app react-conditional-rendering-example

新しいプロジェクトディレクトリに移動します。

  1. cd react-conditional-rendering-example

次に、コードエディタでApp.jsファイルを開きます。 そして、内容を次のコード行に置き換えます。

src / App.js
import React, { Component } from "react";
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: true
    };
  }

  render() {
    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        <button>Login</button>
        <button>Logout</button>
      </div>
    );
  }
}

export default App;

次に、コードエディタでApp.cssファイルを開きます。 そして、内容を次のコード行に置き換えます。

src / App.css
body {
  padding: 1em;
}

h1 {
  font-size: 3em;
  font-weight: 500;
  text-align: center;
  margin-bottom: 1em;
  margin-right: 1em;
  padding: 0;
}

button {
  appearance: none;
  background-color: #246bec;
  border: 1px solid #246bec;
  border-radius: 0;
  box-sizing: border-box;
  color: #ffffff;
  display: block;
  font-size: 2em;
  font-weight: 500;
  margin-bottom: 1em;
  margin-top: 1em;
  padding: .5em;
  width: 100%;
  transition: border-color, background-color 300ms ease-in-out;
}

button:focus {
  border-color: #00006D;
}

button:hover {
  background-color: #0B52D3;
}

button:active {
  background-color: #00006D;
}

次に、ターミナルウィンドウからアプリケーションを実行します。

  1. npm start

そして、ブラウザでアプリケーションを操作します。

各条件付きレンダリングアプローチは、このコードに基づいて構築されます。 この時点でgit commitを作成して、このチュートリアルを進めながら変更をロールバックすることをお勧めします。

この時点で、ログインボタンとログアウトボタンを表示するReactアプリケーションが作成されます。 あなたの目標は、これらのボタンの1つだけを表示させることです。 これを実現するための条件付きレンダリングアプローチを見てみましょう。

1. if…elseステートメントの使用

if…elseステートメントは、条件が満たされたときにifブロックに含まれるアクションを実行します。 それ以外の場合は、elseブロックに含まれるアクションを実行します。

JSXでは、マークアップ付きのJavaScriptコードを使用して、アプリケーション内で動的な値をレンダリングできます。 JSXは、中括弧({および})を使用して、レンダリング前に解釈する必要のある式を示します。 ただし、注意点は、そのような中括弧内で実行できることには制限があるということです。

render()メソッドでif…elseステートメントを使用しようとしたかどうかを考えてみましょう。

警告:これは正しく機能しないコードの例です。 これは、render()メソッドでの解釈の制限の例として示されています。

// ...

class App extends Component {
  // ...

  render() {
    let {isLoggedIn} = this.state;

    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        {
          if(isLoggedIn){
            return <button>Logout</button>
          } else{
            return <button>Login</button>
          }
        }
      </div>
    );
  }
}

// ...

このコードはUnexpected tokenエラーを生成します。 ロジックはrender()メソッドの外に移動する必要があります。

コードエディタでApp.jsファイルを開き、render()メソッドまで下にスクロールして、次の強調表示されたコード変更を行います。

src / App.js
// ...

class App extends Component {
  // ...

  render() {
    let {isLoggedIn} = this.state;

    const renderAuthButton = () => {
      if (isLoggedIn) {
        return <button>Logout</button>;
      } else {
        return <button>Login</button>;
      }
    }

    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        {renderAuthButton()}
      </div>
    );
  }
}

// ...

これは、抽出された関数を作成するプロセスです。 このコードは、JSXから関数renderAuthButtonにロジックを抽出します。 そして、関数はJSX中括弧内で実行されます。

Webブラウザでアプリケーションを開きます。 以前は、ログインボタンとログアウトボタンが表示されていました。 これで、isLoggedIn状態はtrueになり、条件付きロジックではログアウトボタンのみが表示されます。

ここで、代わりにrender()メソッドで複数のreturnを使用しようとしたかどうかを考えてみましょう。

警告:これは、パフォーマンスの低いコードの例であり、避ける必要があります。

// ...

class App extends Component {
  // ...

  render() {
    let {isLoggedIn} = this.state;

    if (isLoggedIn) {
      return (
        <div className="App">
          <h1>
            This is a Demo showing several ways to implement Conditional Rendering in React.
          </h1>
          <button>Logout</button>
        </div>    
      );
    } else {
      return (
        <div className="App">
          <h1>
            This is a Demo showing several ways to implement Conditional Rendering in React.
          </h1>
          <button>Login</button>
        </div>    
      );
    }
  }
}

// ...

上記のスニペットは同じ結果を達成しますが、変更されていないコンポーネントを絶えず再レンダリングした結果としてパフォーマンスの問題が発生する一方で、コンポーネントが不必要に肥大化します。

ベストプラクティスは、兄弟または親コンポーネントの無駄な再レンダリングを回避するために、コンポーネントを可能な限り単純に保つことです。

コードエディタで、新しいAuthButton.jsファイルを作成します。

src / AuthButton.js
import React from "react";

const AuthButton = props => {
  let { isLoggedIn } = props;

  if (isLoggedIn) {
    return <button>Logout</button>;
  } else {
    return <button>Login</button>;
  }
};

export default AuthButton;

AuthButtonは、isLoggedInプロップを介して渡される状態の値に応じて、さまざまな要素またはコンポーネントを返します。

次に、App.jsに再度アクセスし、新しいコンポーネントを使用するように変更します。

src / App.js
import React, { Component } from "react";
import './App.css';
import AuthButton from "./AuthButton";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: true
    };
  }

  render() {
    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        <AuthButton isLoggedIn={isLoggedIn} />
      </div>
    );
  }
}

export default App;

これは、抽出された機能コンポーネントを作成するプロセスです。 このコードは、renderAuthButton()アプローチと同じ結果を生成します。 ただし、変更を別のコンポーネントに移動するという利点があります。

2. switchステートメントの使用

前に示したように、if…elseステートメントを使用して、設定された条件に基づいてコンポーネントから条件付きで異なるマークアップを返すことができます。 同じことは、さまざまな条件のマークアップを指定できるswitchステートメントでも実現できます。

AuthButtonコンポーネントを再検討し、if…elseステートメントをswitchステートメントに置き換えます。

src / AuthButton.js
import React from "react";

const AuthButton = props => {
  let { isLoggedIn } = props;

  switch (isLoggedIn) {
    case true:
      return <button>Logout</button>;
      break;
    case false:
      return <button>Login</button>;
      break;
    default:
      return null;
  }
};

export default AuthButton;

このコードがisLoggedInの値に基づいてさまざまなボタンを返す方法に注目してください。

注: 3つ以上の可能な値または結果がある場合は、switchステートメントメソッドを適用する方が実用的です。

さらに、コンポーネントからnullを返すと、コンポーネントは非表示になります(何も表示されません)。 これは、コンポーネントの表示を切り替える良い方法です。

3. 要素変数の使用

要素変数は、条件付きレンダリングを関数に抽出するアプローチに似ています。 要素変数は、JSX要素を保持する変数です。 JSXの外部でこれらの変数に要素またはコンポーネントを条件付きで割り当て、JSX内でのみ変数をレンダリングできます。

アプリケーションは次のように書き直すことができます。

src / App.js
import React, { Component } from "react";
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: true
    };
  }

  render() {
    let { isLoggedIn } = this.state;
    let AuthButton;

    if (isLoggedIn) {
      AuthButton = <button>Logout</button>;
    } else {
      AuthButton = <button>Login</button>;
    }

    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        {AuthButton}
      </div>
    );
  }
}

export default App;

このコードが条件付きで値(コンポーネント)をAuthButtonに割り当て、後でJSXで参照できることに注意してください。

4. 三項演算子の使用

条件付き(三項)演算子は、3つのオペランドをとる唯一のJavaScript演算子です。 この演算子は、ifステートメントのショートカットとして頻繁に使用されます。

アプリケーションは次のように書き直すことができます。

src / App.js
import React, { Component } from "react";
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: true
    };
  }

  render() {
    let { isLoggedIn } = this.state;

    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        {isLoggedIn ? <button>Logout</button> : <button>Login</button>}
      </div>
    );
  }
}

export default App;

このアプローチにより、コンポーネントが肥大化したり、かさばったり、読みにくくなったりする場合は、機能コンポーネント内に条件をカプセル化できます。

src / AuthButton.js
import React from "react";

const AuthButton = props => {
  let { isLoggedIn } = props;

  return isLoggedIn ? <button>Logout</button> : <button>Login</button>;
};

export default AuthButton;

三項アプローチは、複雑でないif…else評価に役立ちます。 複雑な比較やコンポーネントの場合、プロジェクトが成長するにつれて読みやすさに影響を与える可能性があります。

5. 論理&&の使用(短絡評価)

短絡評価は、式のオペランドの評価中に副作用がないことを確認するために使用される手法です。 論理&&は、アクションが1つの条件でのみ実行されるように指定するのに役立ちます。そうでない場合、アクションは完全に無視されます。

アプリケーションは次のように書き直すことができます。

src / App.js
import React, { Component } from "react";
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: true
    };
  }

  render() {
    let { isLoggedIn } = this.state;

    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        {isLoggedIn && <button>Logout</button>}
      </div>
    );
  }
}

export default App;

このコードは、isLoggedIntrueの場合、ログアウトボタンを表示します。それ以外の場合は、何も表示しません。

次に、Loginボタンに2番目の短絡評価を使用することを検討しましょう。

警告:これは、パフォーマンスの低いコードの例であり、避ける必要があります。

{isLoggedIn && <button>Logout</button>}
{!isLoggedIn && <button>Login</button>}

このコードは、isLoggedInの値に基づいて右ボタンをレンダリングします。 ただし、同じ効果を達成するためのより優れた、よりクリーンな方法があるため、これはお勧めしません。 アプリケーションが大きくなるにつれて、この短絡評価の乱用は煩雑で直感的でないものになる可能性があります。

6. 即時呼び出し関数式(IIFE)の使用

前のセクションでは、JSXの制限により、すべてのタイプのJavaScriptコードを実行できないと述べました。 即時呼び出し関数式(IFFE)を使用すると、これらの制限を回避できます。 IFFEは、定義されるとすぐに実行されるJavaScript関数です。

(function () {
  // statements
})();

この手法を使用すると、JSX内で直接条件付きロジックを記述できますが、そのコードの評価時にすぐに呼び出される無名関数内にラップされます。

アプリケーションは次のように書き直すことができます。

src / App.js
import React, { Component } from "react";
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: true
    };
  }

  render() {
    let { isLoggedIn } = this.state;

    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        {(function() {
          if (isLoggedIn) {
            return <button>Logout</button>;
          } else {
            return <button>Login</button>;
          }
        })()}
      </div>
    );
  }
}

export default App;

これは、矢印関数を使用してもう少し簡潔に記述することもできます。

{(() => {
  if (isLoggedIn) {
    return <button>Logout</button>;
  } else {
    return <button>Login</button>;
  }
})()}

IIFEの詳細については、MDNを参照してください。

7. 拡張JSXライブラリの使用

特定のライブラリは、JSXを拡張する機能を公開し、JSXを使用して条件付きレンダリングを直接実装できるようにします。 そのようなライブラリの1つは、JSX制御ステートメントです。 これはBabelプラグインであり、変換中にコンポーネントのような制御ステートメントを対応するJavaScriptステートメントに変換します。

babel-plugin-jsx-control-statementsパッケージをインストールし、Babel構成を変更した後、アプリケーションは次のように書き直すことができます。

src / App.js
import React, { Component } from "react";
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: true
    };
  }

  render() {
    let { isLoggedIn } = this.state;

    return (
      <div className="App">
        <h1>
          This is a Demo showing several ways to implement Conditional Rendering in React.
        </h1>
        <Choose>
          <When condition={isLoggedIn}>
             <button>Logout</button>;
          </When>
          <When condition={!isLoggedIn}>
             <button>Login</button>;
          </When>
        </Choose>
      </div>
    );
  }
}

export default App;

ただし、作成したコードは最終的に通常のJavaScript条件付きにトランスパイルされるため、このアプローチはお勧めしません。 些細なことに依存関係を追加するよりも、JavaScriptを作成する方が常に良いでしょう。

条件付きレンダリングアプローチの選択

原則として、条件付きレンダリングを実装する際には、次のことを確認するのが最善です。

詳細については、ColeWilliamsによるReactの高性能条件に関するこの記事を参照してください。

考慮すべき事項は次のとおりです。

一般に、次の推奨事項に留意してください。

これらは推奨事項であり、規則ではないことに注意してください。 プロジェクトのニーズと慣習により、これらの推奨事項に従わないアプローチを採用する必要がある場合があります。

結論

この記事では、Reactアプリケーションで条件付きレンダリングを実装する7つの方法を検討しました。 それぞれの方法には独自の利点があり、どちらを使用するかの選択は主にユースケースに依存します。

詳細については、条件付きレンダリングのドキュメントを参照してください。

高次コンポーネントおよびHOCを使用した条件付きレンダリングで学習を続けてください。

モバイルバージョンを終了