条件付きレンダリングはReactの強力な機能です。これを使って特定の条件に基づいてコンポーネントをレンダリングすることができます。

動的かつインタラクティブなウェブアプリケーションを構築する上で、重要な役割を果たす基本的な概念です。

今回の記事では、Reactの条件付きレンダリングについて深く掘り下げ、基本的なテクニックと高度なテクニックを、正しい理解のための例とともに説明します。

Reactの条件付きレンダリング

Reactの条件付きレンダリングでは、変数、状態、またはpropsに格納する特定の値に基づいて、画面に表示されるコンテンツを動的に制御することができます。

これは、特定のUI要素を表示または非表示にしたり、ページのレイアウトを変更したり、ユーザーの操作に基づいて別のコンテンツをレンダリングしたりする場合に非常に便利です。

条件付きレンダリングは、Reactアプリケーションにおいて重要です。というのも、変化するデータやユーザーインタラクションにリアルタイムで対応できる、動的なユーザーインターフェースを作成することができるからです。

また、不要なコンポーネントや要素のレンダリングを回避することで、アプリケーションのパフォーマンスと効率を向上させることができます。

条件付きレンダリングの基本テクニック

Reactで条件付きレンダリングに使用できる基本的なテクニックをいくつか見ていきましょう。

条件付きレンダリングにif文を使用する

Reactで条件付きレンダリングを実装するお手軽な方法が、ifの使用です。

if (condition) {
    return <p>Expression 1</p>;
  } else {
    return <p>Expression 2</p>;
  }

JavaScriptのif文は、コンポーネントのrender()メソッド内で使用することで、特定の条件に基づいてコンテンツを条件付きでレンダリングすることができます。

たとえば、データの読み込みを待つ間にスピナーを表示するには、次のようなif文を使用します。

import { useState, useEffect } from 'react';
import Spinner from './Spinner';

const MyComponent = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    // Fetch data from an API
    fetch('https://example.com/data')
      .then((response) => response.json())
      .then((data) => {
        setData(data);
        setIsLoading(false);
      });
  }, []);

  if (isLoading) {
    return <Spinner />;
  }

  return <div>{/* Render the data here */}</div>;
};

export default MyComponent;

この例では、MyComponentuseEffectフックを使ってAPIからデータを取得します。データの読み込みを待つ間に、ifを使用してスピナーコンポーネントを表示しています。

また、コンポーネントのレンダリング中にエラーが発生した場合に、フォールバックUIをレンダリングするという手もあります。

const MyComponent = ({ data }) => {
  if (!data) {
    return <p>Something went wrong. Please try again later.</p>;
  }

  return <div>{/* Render the data here */}</div>;
};

export default MyComponent;

このコードでは、MyComponentdataを受け取ります。 dataに問題がある場合には、 ステートメントを使用してエラーメッセージをレンダリングします。

また、以下にあるように、ifを使用して、ユーザー役割ごとに異なるコンテンツを表示することができます。

const MyComponent = ({ user }) => {
  if (user.role === 'admin') {
    return <p>Welcome, admin!</p>;
  } else if (user.role === 'user') {
    return <p>Welcome, user!</p>;
  } else {
    return <p>You are not authorized to access this page.</p>;
  }
};

export default MyComponent;

このコードでは、MyComponentuserプロパティを受け取ります。user.roleプロパティに応じ、ifを使用して異なるコンテンツを表示することができます。

条件付きレンダリングに三項演算子を使用する

Reactで条件付きレンダリングを実装するもう1つの方法に、JSXの三項演算子(?)があります。

三項演算子では、3つのオペランドを指定することで、コンパクトなインラインのif-else文を記述することができます。最初のオペランドは条件、残りの2つのオペランドは式です。条件がtrueの場合は、最初の式が実行され、そうでない場合は、2番目の式が実行されます。

例えば、以下のようにpropsに基づき異なるコンポーネントをレンダリングすることができます。

import ComponentA from './ComponentA';
import ComponentB from './ComponentB';

const ExampleComponent = ({ shouldRenderComponentA }) => {
  return (
    <div>
      {shouldRenderComponentA ? <ComponentA /> : <ComponentB />}
    </div>
  );
};

export default ExampleComponent;

このコードでは、ExampleComponentshouldRenderComponentAを受け取ります。そして、三項演算子を使って、プロパティの値に基づいてComponentAComponentBのいずれかを条件付きでレンダリングしています。

また、状態によって異なるテキストをレンダリングすることもできます。

import { useState } from 'react';

const ExampleComponent = () => {
  const [showMessage, setShowMessage] = useState(false);

  return (
    <div>
      <button onClick={() => setShowMessage(!showMessage)}>
        {showMessage ? 'Hide message' : 'Show message'}
      </button>
      {showMessage ? <p>Hello, world!</p> : null}
    </div>
  );
};

export default ExampleComponent;

この例では、三項演算子を使用して、showMessageの状態の値によって異なるテキストを条件付きでレンダリングしています。ボタンがクリックされると、showMessageの値が切り替わり、それに応じてテキストが表示または非表示になります。

最後に、データの取得中にスピナーをレンダリングすることもできます。

import { useState, useEffect } from 'react';
import Spinner from './Spinner';

const ExampleComponent = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const jsonData = await response.json();
      setData(jsonData);
      setIsLoading(false);
    };
    fetchData();
  }, []);

  return (
    <div>
      {isLoading ? <Spinner /> : <p>{data.title}</p>}
    </div>
  );
};

export default ExampleComponent;

この例では、三項演算子を使って、APIからデータを取得している間、条件付きでスピナーを表示しています。データが利用可能になると、三項演算子を使用してtitleプロパティをレンダリングします。

条件付きレンダリングにAND演算子やOR演算子を使用する

Reactで条件付きレンダリングを実装するには、AND(&& )やOR(||)演算子を使用することも可能です。

AND演算子では、ある条件が真である場合にのみコンポーネントをレンダリングし、OR演算子では、どちらかの条件が真である場合にコンポーネントをレンダリングします。

これらの演算子は、コンポーネントをレンダリングするかどうかを決定する単純な条件がある場合に便利です。例えば、フォームが有効な場合にのみボタンをレンダリングしたい場合は、次のようにAND演算子を使用できます。

import { useState } from 'react';

const FormComponent = () => {
  const [formValues, setFormValues] = useState({ username: "", password: "" });

  const isFormValid = formValues.username && formValues.password;

  const handleSubmit = (event) => {
    event.preventDefault();
    // Submit form data
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={formValues.username}
        placeholder="Type Username..."
        onChange={(e) =>
          setFormValues({ ...formValues, username: e.target.value })
        }
      />
      <br />
      <input
        type="password"
        value={formValues.password}
        placeholder="Type Password..."
        onChange={(e) =>
          setFormValues({ ...formValues, password: e.target.value })
        }
      />
      {isFormValid && <button type="submit">Submit</button>}
    </form>
  );
};

export default FormComponent;

この例では、usernamepasswordの2つの入力フィールドのあるフォームを、FormComponentで扱っています。useStateフックを使ってフォームの値を管理し、isFormValid変数を使用して両方の入力フィールドに値があるかどうかをチェックしています。AND演算子(&&)を使って、isFormValidがtrueのときだけ送信ボタンを表示するようにしています。これにより、フォームが有効なときだけボタンをクリックすることができます。

同様に、OR演算子を使って、データの読み込みが完了していない時には読み込み中メッセージを、エラーが発生した場合はエラーメッセージをレンダリングすることができます。

import React, { useEffect, useState } from 'react';

const DataComponent = () => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [errorMessage, setErrorMessage] = useState('');

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        setData(data);
      } catch (error) {
        setErrorMessage('An error occurred while fetching data.');
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, []);

  return (
    <>
      {errorMessage || isLoading ? (
        <p>{errorMessage || 'Loading...'}</p>
      ) : (
        <ul>
          {data.map((item) => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      )}
    </>
  );
};

export default DataComponent;

この例では、DataComponentでfetchを使ってAPIからデータを取得し、それをリストとして表示しています。データ、読み込み状態、エラーメッセージを管理するために、useStateフックを使用しています。論理和演算子(||)を使うと、どちらかの条件が真であれば、読み込み中メッセージやエラーメッセージを表示することができます。これにより、データ取得プロセスの現在の状態を示すメッセージがユーザーに対して正しく表示されます。

Reactの条件付きレンダリングにANDおよびOR演算子を使用することで、単純な条件を簡潔な記述で処理することができます。しかし、より複雑なロジックには、switch文などの他のアプローチを使用することをおすすめします。

条件付きレンダリングの高度なテクニック

Reactの条件付きレンダリングは、アプリケーションの要件に応じて、より複雑にすることができます。続いては、複雑な状況で条件付きレンダリングに使用できる高度なテクニックをいくつかご紹介します。

条件付きレンダリングにSwitch文を使用する

条件付きレンダリングでは、if文や三項演算子が一般的ですが、特に複数の条件を扱う場合は、switch文の方が適切なことがあります。

以下がその例です。

import React from 'react';
const MyComponent = ({ userType }) => {
  switch (userType) {
    case 'admin':
      return <p>Welcome, admin user!</p>;
    case 'user':
      return <p>Welcome, regular user!</p>;
    default:
      return <p>Please log in to continue.</p>;
  }
};
export default MyComponent;

このコードでは、switch文を使用して、userTypeに基づくコンテンツを条件付きでレンダリングしています。このアプローチは、複数の条件を扱うときに便利で、複雑なロジックを扱いながらも、整理しながら可読性を確保することができます。

条件付きレンダリングにReact Routerを使用する

React Routerは、Reactアプリケーションでクライアントサイドのルーティングを処理することのできるライブラリです。React Routerを使用すると、現在のルートに基づいてコンポーネントを条件付きでレンダリングすることができます。

以下に、React Routerを使った条件付きレンダリングの実装例を示します。

import { useState } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

import Home from './components/Home';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
import NotFound from './components/NotFound';

const App = () => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/login">
          <Login setIsLoggedIn={setIsLoggedIn} />
        </Route>
        {isLoggedIn ? (
          <Route path="/dashboard" component={Dashboard} />
        ) : (
          <Route component={NotFound} />
        )}
      </Switch>
    </Router>
  );
};

export default App;

このコードでは、isLoggedInの状態を使用して、ユーザーがログインしている場合はDashboard コンポーネントを、ユーザーがログインしていない場合はNotFoundコンポーネントを条件付きでレンダリングしています。Loginコンポーネントは、ユーザーがログインに成功すると、isLoggedInの状態をtrueに設定します。

LoginコンポーネントとsetIsLoggedIn関数を渡すために、<Route>コンポーネントのchildren propsを使用しています。これにより、pathで指定することなく、Loginコンポーネントにプロパティを渡すことができます。

まとめ

条件付きレンダリングはReactの強力なテクニックで、さまざまな条件に基づいてUIを動的に更新することができます。

アプリケーションのUIロジックの複雑さに応じて、開発現場に適したアプローチを選択することをおすすめします。

また、条件付きレンダリングのロジックがあらゆる状況で問題なく動作するよう、念を入れてテストすることをお忘れなく。

Reactアプリケーションのための理想的なホスティングソリューションをお探しなら、Kinstaのアプリケーションホスティングをお試しください。無料利用枠をご用意しています。

Joel Olawanle Kinsta

Kinstaでテクニカルエディターとして働くフロントエンド開発者。オープンソースをこよなく愛する講師でもあり、JavaScriptとそのフレームワークを中心に200件以上の技術記事を執筆している。