条件付きレンダリングの技法:ReactとNext.js開発者向けのヒントとコツ
Kumar Harsh
2023年10月30日
0 分で読めます条件付きレンダリングとは、ユーザーの認証状態や権限、アプリケーションの状態などの条件に基づいて、複数の候補から特定のコンポーネントだけをレンダリングするWebアプリケーションの手法です。また、クライアントサイドルーティングや遅延読み込みなど、Reactの基本的なUI機能を幅広く実装する際にも利用できます。
この記事では、条件付きレンダリングのメリットや条件付きルーティングとの違い、React、Next.js、Remixでそれぞれを実装する方法を解説します。
Reactにおける条件付きレンダリングのメリット
ReactやReact系フレームワークで構築されたアプリで条件付きレンダリングを活用すると、読み込み時間の短縮など、さまざまなメリットが得られます。
Webアプリケーションの読み込み時間は、読み込むページのDocument Object Model(DOM)のサイズに左右されます。特に、ユーザーがスクロールしないと表示されない要素を含め、多くの要素を保持していると、DOMサイズが不必要に大きくなり、アプリケーションのパフォーマンスが低下することがあります。
このような場合は、必要になるまでリソースの読み込みを遅らせる一般的な手法である遅延読み込みを実装し、ユーザーがスクロールして要素がビューポートに入るまで、コンポーネントのレンダリングを遅らせることができます。Reactで特に広く使われている遅延読み込みライブラリの1つ、react-lazyloadは条件付きレンダリングを利用し、コンポーネントがブラウザーのビューポートに入ったとき、つまりユーザーに見える状態になったときにのみレンダリングします。
パフォーマンスの向上に加え、条件付きレンダリングはユーザーエクスペリエンスの改善にも役立ちます。認証状態(つまり未認証ユーザーにはログインボタン、認証済みユーザーにはログアウトボタンを同じ場所に表示する)やアクセス権限(つまりツイートなどのコンテンツの所有者には編集コントロールや詳細な分析情報を表示し、所有者以外には限られた情報を表示する)など、ユーザーの属性に応じてUIをカスタマイズできます。
さらに、条件付きレンダリングを使えば、データ取得やバックエンドとの通信などのクライアントサイド処理をスムーズに扱えます。処理中にローディングバーを表示したり、リモートソースからデータを読み込んでいる間は空のリストを非表示にしたりできます。
条件付きレンダリングは、react-routerパッケージなどを使った、シングルページReactアプリのクライアントサイドルーティングも可能にします。
つまり、条件付きレンダリングはReactで使われる最も重要な手法の1つと言えるでしょう。
条件付きレンダリングと条件付きルーティングの違い
条件付きレンダリングについて話すと、条件付きルーティングもよく話題になります。条件付きルーティングは、ユーザーやアプリケーションの状態などの条件に基づいてユーザーに表示する内容を制御する点で、条件付きレンダリングと似ています。ただし、コンポーネントをレンダリングまたは破棄するのではなく、ユーザーをあるルート(またはページ)から別のルートへ移動させます。これはアクセス制御の観点から役立ちます。
WebアプリにはURLから直接アクセスできます。つまり、アプリ内のページのURLは、そのページが公開されているかどうかにかかわらず、ユーザーに取得・保存される可能性があります。特定のロールを持つユーザーだけがアクセスできる個人プロフィールや設定ページなど、権限が必要なページのURLが悪用され、制限されたコンテンツへのアクセスが試みられる恐れがあります。
条件付きルーティングを使うと、Reactアプリはページのレンダリングを要求するリクエストに対して、要求元にそのルートへのアクセス権限があるかどうかを確認できます。権限がなければレンダリングを拒否し、別のページにリダイレクトします。リダイレクト先のページでは、認証を求めたり、アクセスが拒否されたことをユーザーに知らせたりするのが一般的です。
たとえば、新しいシークレットウィンドウでhttps://mail.google.com/mailにアクセスして、条件付きルーティングがどのように機能するかを確かめてみましょう。Googleのログインページにリダイレクトされます。これが、裏側で条件付きルーティングが機能している例です。
ただし、SPAの条件付きルーティングはセキュリティを保証するものではありません。Reactアプリ(シングルページ)が未認証ユーザーをリダイレクトする前でも、権限が必要なページのコンテンツはJavaScriptソースコードに含まれています。そのため、権限のないユーザーがデータにアクセスする事態につながる可能性があります。したがって、Next.jsやRemixなどのフレームワークを使い、認証に関連する条件付きルーティングはサーバーサイドで設定するのが最善です。
Reactで条件付きレンダリングを実装する
条件付きレンダリングについて理解したところで、次のセクションではプログラミングの基本概念の1つであるif…else文を使い、Reactアプリに実装する方法を説明します。
まず、次のコマンドを実行して新しいReactアプリを作成します。
アプリの準備ができたら、次のコードをsrc/App.jsファイルに貼り付けます。
このコードには、実装方法を説明するインラインコメントが含まれています。
次に、以下のコマンドを実行してアプリを起動します。
アプリのURL(つまりhttp://localhost:3000)にアクセスすると、画面にテキストとボタンが表示されます。

Log Inボタンをクリックして状態を変更し、再レンダリングを実行してみましょう。ログイン済みユーザー向けのテキストとボタンに切り替わることがわかります。

以上です。Reactでの条件付きレンダリングは簡単に実装できます。次は、Next.jsアプリでの方法を見ていきましょう。
Next.jsで条件付きレンダリングと条件付きルーティングを実装する
Next.jsは、意見の定まった本番環境向けのオープンソースReactベースフレームワークで、高いパフォーマンスを発揮するWebアプリの構築を支援します。2016年にVercelがリリースし、以来、Web開発業界を代表するReactベースのフレームワークの1つに成長しました。
Next.jsは標準でサーバーサイドレンダリングと静的レンダリングに対応し、データ取得、ルーティング、サーバーランタイムなど、開発でよくある課題を解決する使いやすい機能を提供します。
Next.jsで条件付きレンダリングを実装する方法
Next.jsとReactではJSXの構文が共通しているため、Reactと同じ条件付きレンダリングの手法をNext.jsにも適用できます。
Next.jsを始めるには、次のコマンドを実行して新しいNext.jsアプリを作成します。
画面に表示される指示に従ってアプリを作成します。デフォルトの選択肢を選べますが、TypeScriptについてはNoを選択してください。プロジェクトを作成したら、次のコードをpages/index.jsファイルに貼り付けます。
このコードには、各ステップで何が行われるかを説明するインラインコメントが含まれています。Reactの例と大きく異なる点として、レンダリング時に2つのコンポーネントから一方を選ぶために、JavaScriptの三項条件演算子を使っています。次のコマンドでアプリを起動できます。
アプリが起動すると、http://localhost:3000に次のような画面が表示されます。

もう一度、Log Inボタンをクリックして状態を変更してみましょう。

Next.jsで条件付きルーティングを実装する方法
Next.js 10以降では、条件付きルーティングも簡単に実装できます。まず、conditionals-next/pagesディレクトリに新しいprofile.jsファイルを作成し、次のコードスニペットを貼り付けます。
次に、アプリを再度起動してhttp://localhost:3000/profileにアクセスします。すぐにホームページ(つまり/ルート)にリダイレクトされます。ターミナルでリダイレクトのログを確認できます。
allowAccessの値をtrueに変更すると、プロフィールページを表示できます。

Remixで条件付きレンダリングと条件付きルーティングを実装する
Remixは、Web標準を重視し、優れたユーザーエクスペリエンスの構築を支援する、成長中のもう1つのReactベースWebアプリ構築フレームワークです。Remixは2021年にオープンソース化され、Next.jsの有力な競合となりました。
Remixは完全なサーバーサイドレンダリングに対応したフレームワークで、エラーバウンダリーやトランジション処理などの機能を備えています。
Remixで条件付きレンダリングを実装する方法
RemixはReactをベースとしているため、ReactやNext.jsと同様の方法で条件付きレンダリングを実装できます。
まず、次のコマンドを実行して新しいRemixプロジェクトを作成します。
画面の指示に従ってプロジェクトを作成します。TypeScriptではなくJavaScriptを選択してください。プロジェクトを作成したら、app/routes/index.jsxに次のコードスニペットを貼り付けます。
このコードスニペットには、各ステップで何が行われるかを説明するインラインコメントが含まれています。この例ではif...else文や三項条件演算子の代わりに、switch文を使ってレンダリングするコンポーネントを決定しています。
これまでの例と同様に、ホームページはhttp://localhost:3000で次のように表示されます。

これまでと同様に、Log Inボタンをクリックして状態を変更してみましょう。

Remixで条件付きルーティングを実装する方法
Next.jsでサーバーサイドの条件付きルーティングを実装したのと同じように、Remixでも実装できます。conditionals-remix/app/routesディレクトリにprofile.jsxファイルを新しく作成し、次のコードを貼り付けます。
ここではgetServerSideProps関数の代わりにloader関数を使います。Remixは、サーバー上でコンポーネントをレンダリングする際のデータ読み込みにloaderをサポートしており、これはNext.jsのgetServerSidePropsと同様の機能です。また、allowAccessがfalseの場合にリダイレクトを開始するため、ユーティリティ関数redirect(Next.jsのredirect関数に相当)を返します。
http://localhost:3000/profileにアクセスすると、もう一度すぐにホームページ(つまり/ルート)にリダイレクトされます。ターミナルでリダイレクトのログを確認できます。
allowAccessの値をtrueに変更すると、プロフィールページを表示できるようになります。

条件付きレンダリングに関するその他の考慮事項
条件付きレンダリングを使う際、仮想DOMへの影響が気になるかもしれません。条件付きレンダリングのさまざまな方法でパフォーマンスに違いはあるのでしょうか?条件付きレンダリングの詳細を隠すために新しいコンポーネントや高階コンポーネント(HOC)を作ると、アプリのDOMやパフォーマンスに影響するのでしょうか?このセクションでは、こうした疑問への答えを解説します。
条件付きレンダリングとJSX
条件付きレンダリングの実装方法によって、アプリのDOMやパフォーマンスに影響が出ることはありません。次の例を見てみましょう。
三項条件演算子を使って、次のように書くこともできます。
どちらの場合も、親コンポーネントが2つのコンポーネント(つまりLoginButtonとLogoutButton)のうち一方を返し、DOMにはまったく同じ変更が生じます。どちらの場合も異なるボタンタグのインスタンスが返されるのでは、と考えるかもしれませんが、それは誤りです。ボタンなどのJSX要素はインスタンスではなく、最終的なHTML構造を表す記述、つまり骨組みにすぎないからです。
同じ構造で同じ要素を返す限り、DOMへの影響は変わりません。つまり、JSXの構造が同じであれば、レンダリングを自由にコンポーネントの内部に抽象化できます。
これにより、構造がまったく同じ2つのコンポーネントが1つの状態を共有し、そのうち一方だけがDOMの同じ場所で条件付きレンダリングされる、といった興味深い状況も生まれます。詳しくはReactのWebサイトをご覧ください。JSXの単純な三項演算子がアプリの動作にどれほど大きな影響を与えるかが紹介されています。
ネストされたコンポーネントと条件付きレンダリング
コンポーネントの定義をコンポーネント内にネストするのは、アンチパターンと見なされています。主な理由の一つは、DOMツリー内の位置にかかわらず、親コンポーネントが再レンダリングされるたびに、ネストされたコンポーネントが再作成されることです。この動作は先ほど見たものとは異なります。ランタイムでは、親コンポーネントの再レンダリング時にネストされたコンポーネントの定義が再作成されるためです。これは、ネストされたコンポーネントの定義の新しいインスタンスが作成されるのに近く、それがこの問題を引き起こします。
まとめと参考リソース
条件付きレンダリングは一見すると(実際にも)とてもシンプルですが、Reactアプリのパフォーマンスとユーザー体験を向上させる強力な手法です。この記事では、そのメリットや条件付きルーティングとの違いに加え、React、Next.js、Remixでの実装方法を紹介しました。
条件付きレンダリングや、レンダリング間でReactが状態をどのように扱うかについて詳しく知りたい方は、ぜひ新しいReactドキュメントをご覧ください。
Reactアプリの開発では、ルーティングや状態管理などの機能を追加するために、npmパッケージを選んでインストールすることがよくあります。Snyk Advisorを活用すれば、アプリの高いセキュリティ基準を維持しながら、プロジェクトに最適なnpmパッケージを見つけられます。また、Reactの開発で実践すべきセキュリティのベストプラクティス10選もご覧ください。
SnykはIDE拡張機能としても利用でき、Reactのコードベースに潜む安全でないコードを見つけたり、オープンソースの依存関係にあるセキュリティ上の脆弱性の修正に役立ちます。
CTFを始めよう
オンデマンドのバーチャル入門ワークショップを視聴して、CTFの課題の解き方を学びましょう。



