1. ホーム
  2. React

【React】条件分岐とリスト表示の使い方|map・三項演算子・&& でUIを出し分ける

Share

React では「ログイン中だけ表示する」「配列のデータを一覧にして並べる」といった、条件によって画面の見た目を変える処理がよく登場します。ところが JSX の中には if 文をそのまま書けないため、最初はどう表現すればよいか戸惑いがちです。この記事では、三項演算子と && 演算子による条件分岐、map を使ったリスト表示、そしてリストに欠かせない key 属性まで、初心者がつまずきやすいポイントを押さえながら解説します。

JSX の中に if 文は書けない

まず前提として、JSX の { } の中に書けるのは「値を返す式」だけです。if 文や for 文は「値を返さない文」なので、JSX の波かっこの中に直接書くことはできません。そのため React の条件分岐には、値を返せる三項演算子&& 演算子を使います。

もし if 文で分けたい場合は、JSX を書く前(return の外側)で変数に代入しておき、その変数を JSX に埋め込みます。次のコードで両方の書き方を見比べてみましょう。

Greeting.jsx
function Greeting({ isLogin }) {
  // if 文は JSX の外で使う
  let message;
  if (isLogin) {
    message = <p>おかえりなさい</p>;
  } else {
    message = <p>ログインしてください</p>;
  }

  return <div>{message}</div>;
}

この書き方でも問題なく動きますが、分岐がシンプルなときはコードが冗長になりがちです。そこで JSX の中に直接書ける三項演算子がよく使われます。

三項演算子で2択を出し分ける

三項演算子は 条件 ? 真のとき : 偽のとき という形で、条件に応じて2つの値のどちらかを返します。値を返す式なので、JSX の波かっこの中にそのまま書けます。先ほどの例を三項演算子で書き直すと、次のようにすっきりします。

Greeting.jsx
function Greeting({ isLogin }) {
  return (
    <div>
      {isLogin
        ? <p>おかえりなさい</p>
        : <p>ログインしてください</p>}
    </div>
  );
}

isLogintrue のときは「おかえりなさい」、false のときは「ログインしてください」が表示されます。文字列やクラス名の一部だけを切り替えることもでき、たとえば className={isActive ? 'on' : 'off'} のように属性の値としても使えます。ただし、三項演算子の中にさらに三項演算子を入れ子にすると一気に読みにくくなるので、分岐が3つ以上になるときは if 文で変数に組み立てるか、コンポーネントを分けることを検討しましょう。

&& 演算子で「あるときだけ表示」する

「条件を満たすときだけ表示し、満たさないときは何も出さない」という片側だけの分岐には、論理AND演算子 && が便利です。JavaScript の && は、左辺が真なら右辺を、左辺が偽なら左辺の値をそのまま返します。React では falsenullundefined は画面に何も描画しないため、これを利用して表示・非表示を切り替えられます。

Notification.jsx
function Notification({ hasNews }) {
  return (
    <div>
      <h1>ホーム</h1>
      {/* hasNews が true のときだけ表示される */}
      {hasNews && <p>新しいお知らせがあります</p>}
    </div>
  );
}

hasNewstrue のときは <p> が表示され、false のときは何も表示されません。三項演算子で「偽のときは null」と書くこともできますが、片側だけ表示するなら && のほうが簡潔です。なお、else 側にも何か出したいときは三項演算子を使い、出さなくてよいときは && を使う、と覚えておくと選びやすくなります。

&& の左辺が数値の 0 だと画面に 0 が出る

&& でとくにハマりやすいのが、左辺に数値を書いてしまうケースです。たとえば「件数が1件以上あるときだけバッジを出したい」つもりで、次のように書いたとします。

Cart.jsx
function Cart({ count }) {
  return (
    <div>
      {/* ❌ count が 0 のとき、画面に「0」が表示されてしまう */}
      {count && <span className="badge">{count}</span>}
    </div>
  );
}

count0 のとき、0 && ... は左辺の 0 をそのまま返します。ここで問題なのは、React は false は描画しないのに、数値の 0 はそのまま文字として描画するという点です。その結果、バッジは消えても画面に「0」だけがぽつんと残ってしまいます。

これを防ぐには、左辺を必ず真偽値(true / falseにします。count > 0 のように比較して条件式にするか、三項演算子で明示的に null を返すのが確実です。

Cart.jsx
// ✅ 比較して真偽値にする
{count > 0 && <span className="badge">{count}</span>}

// ✅ 三項演算子で偽のときは null を返す
{count ? <span className="badge">{count}</span> : null}

どちらも「0 のときは何も表示しない」という意図どおりに動きます。&& の左辺には、数値ではなく必ず真偽値になる条件式を置く——これが 0 表示問題を避けるコツです。空文字列 '' も同様に注意が必要なので、文字列の有無で分岐するときは text.length > 0 && ... のように書くと安全です。

map で配列をリスト表示する

データの配列をそのまま画面に並べたいときは、配列の map メソッドを使います。map は配列の各要素を別の値に変換して新しい配列を返すメソッドで、React では「データの配列を JSX 要素の配列に変換する」目的で使います。返された JSX の配列を波かっこに入れると、React がそれぞれを順番に描画してくれます。

FruitList.jsx
function FruitList() {
  const fruits = ['りんご', 'バナナ', 'みかん'];

  return (
    <ul>
      {fruits.map((fruit) => (
        <li key={fruit}>{fruit}</li>
      ))}
    </ul>
  );
}

fruits.map((fruit) => ...) で、配列の各要素から <li> を作っています。アロー関数のかっこを ( ) にすると return を省略して JSX をそのまま返せるので、リスト表示ではこの書き方が定番です。実際のアプリでは、次のようにオブジェクトの配列を扱うことがほとんどです。

TodoList.jsx
function TodoList() {
  const todos = [
    { id: 1, title: '買い物に行く' },
    { id: 2, title: '本を読む' },
    { id: 3, title: '掃除をする' },
  ];

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

各オブジェクトが持つ idkey に、title を表示内容に使っています。この key がリスト表示ではとても重要なので、次で理由を見ていきます。

key 属性が必要な理由と、index を使うときの注意

map で要素を並べるとき、それぞれに key という特別な属性を付けないと、コンソールに Warning: Each child in a list should have a unique "key" prop. という警告が出ます。key は、React が「どの要素がどのデータに対応しているか」を見分けるための目印です。

React はリストが変化したとき、key を手がかりに「どの要素が追加・削除・並び替えされたか」を効率よく判断します。key がないと React は変化を正しく追えず、余計な再描画が起きたり、入力中の値が別の行に移ってしまうなどの不具合につながります。そのため key には、データを一意に識別できる値(多くはデータベースの id)を渡すのが基本です。

map の第2引数で受け取れる配列のインデックス(index)を key に使うこともできますが、これは並び替え・追加・削除が起きるリストでは避けるべきです。要素を並び替えても index は 0, 1, 2… のまま変わらないため、React が別のデータを同じ要素と勘違いし、表示が崩れることがあります。

key-example.jsx
// ✅ 一意な id があるならそれを使う
{todos.map((todo) => (
  <li key={todo.id}>{todo.title}</li>
))}

// △ index は「並び替えも増減もしない」リストに限る
{todos.map((todo, index) => (
  <li key={index}>{todo.title}</li>
))}

表示するだけで並び順が変わらない静的なリストなら index でも実害は出ませんが、迷ったら id を用意して使うのが安全です。なお key は React が内部で使う特別な属性で、コンポーネントの props としては渡らない点も覚えておきましょう。

空配列のときに「データがありません」を出す

条件分岐とリスト表示は組み合わせて使う場面が多くあります。よくあるのが、配列が空のときは一覧の代わりにメッセージを表示するパターンです。三項演算子で「要素があるかどうか」を判定し、あれば map の結果を、なければメッセージを表示します。

TodoList.jsx
function TodoList({ todos }) {
  return (
    <div>
      <h2>やることリスト</h2>
      {todos.length > 0 ? (
        <ul>
          {todos.map((todo) => (
            <li key={todo.id}>{todo.title}</li>
          ))}
        </ul>
      ) : (
        <p>やることはまだありません</p>
      )}
    </div>
  );
}

todos.length > 0 で配列が空かどうかを判定しています。ここでも && の 0 表示問題と同じ理由で、todos.length && ... と書くと配列が空のとき画面に「0」が出てしまうため、length > 0 と比較するか三項演算子を使うのが安全です。このように、リストを表示する前に「データがあるか」を確認しておくと、空のときも自然な画面になります。

まとめ

React では JSX の中に if 文を書けないため、条件分岐には値を返す式を使います。2択の出し分けには 条件 ? A : B の三項演算子、「あるときだけ表示」には 条件 && 要素&& 演算子が便利です。ただし && の左辺に数値の 0 や空文字列を置くと画面にそのまま表示されてしまうので、count > 0 のように必ず真偽値になる条件式を書きます。配列のリスト表示には map を使い、各要素には一意な idkey に渡します。index を key にするのは並び替えや増減のないリストに限りましょう。さらに todos.length > 0 の判定と組み合わせれば、空のときにメッセージを出すといった実用的な UI も作れます。これらを押さえれば、React で「状況に応じて変わる画面」を思いどおりに組み立てられるようになります。

参考ページ