0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】ReactでFor文は使えない?繰り返し処理の正しい実装方法を徹底解説

Posted at

はじめに

Reactで開発を始めた方が最初につまずくポイントの一つが、「for文が使えない」という問題です。正確に言えば、JSXの中では直接for文を記述できません。

この記事では、なぜJSX内でfor文が使えないのか、そしてReactで繰り返し処理を行う正しい方法について解説します。

この記事で学べること

  • JSXにおける式と文の違い
  • map()メソッドを使った繰り返し処理の実装方法
  • keyプロパティの重要性と正しい使い方
  • どうしてもfor文を使いたい場合の対処法

JSXにおける式と文の違い

式と文の基本概念

JavaScriptには式(expression)と文(statement)という2つの概念があります。

式(expression)は、評価すると値を返すコードです。例えば以下のようなものが式に該当します。

// 式の例
1 + 2                    // 3という値を返す
user.name                // プロパティの値を返す
isActive ? 'active' : '' // 三項演算子は値を返す
[1, 2, 3].map(n => n * 2) // 新しい配列を返す

一方、文(statement)は、何らかの処理を実行するコードで、値を返しません。

// 文の例
if (isActive) { }        // 条件分岐を実行
for (let i = 0; i < 10; i++) { } // ループ処理を実行
let count = 0;           // 変数宣言を実行

なぜJSX内でfor文が使えないのか

JSXの中括弧{}内には、式しか記述できないという制約があります。これは、JSXが最終的にJavaScriptの関数呼び出しに変換されるためです。

// これはOK(式なので)
<div>{user.name}</div>
<div>{isActive ? 'アクティブ' : '非アクティブ'}</div>

// これはNG(文なので)
<div>{if (isActive) { return 'アクティブ' }}</div>
<div>{for (let i = 0; i < 10; i++) { }}</div>

以下の図は、JSXで使える構文と使えない構文を分類したものです。

Reactでの繰り返し処理:基本編

map()メソッドを使った実装

Reactで繰り返し処理を行う際は、配列のmap()メソッドを使うのが標準的な方法です。map()は新しい配列を返す式なので、JSX内で問題なく使用できます。

function UserList() {
  const users = ['田中', '佐藤', '鈴木'];
  
  return (
    <ul>
      {users.map((user, index) => (
        <li key={index}>{user}</li>
      ))}
    </ul>
  );
}

このコードでは、users配列の各要素に対して<li>要素を生成しています。map()の第一引数は配列の各要素、第二引数はインデックスです。

基本的な配列のレンダリング例

数値の配列やオブジェクトの配列など、さまざまなデータ型に対応できます。

// 数値の配列
function NumberList() {
  const numbers = [1, 2, 3, 4, 5];
  
  return (
    <ul>
      {numbers.map((number) => (
        <li key={number}>{number}の2倍は{number * 2}</li>
      ))}
    </ul>
  );
}

// オブジェクトの配列
function ProductList() {
  const products = [
    { id: 1, name: 'ノートPC', price: 120000 },
    { id: 2, name: 'マウス', price: 3000 },
    { id: 3, name: 'キーボード', price: 8000 }
  ];
  
  return (
    <ul>
      {products.map((product) => (
        <li key={product.id}>
          {product.name}: {product.price.toLocaleString()}</li>
      ))}
    </ul>
  );
}

オブジェクトの配列を扱う場合は、各オブジェクトのプロパティにアクセスして表示できます。このように、map()を使えば柔軟にデータを表示できますね。

keyプロパティの重要性

keyが必要な理由

繰り返し処理で要素を生成する際、各要素には必ずkeyプロパティを指定する必要があります。keyはReactが要素を識別し、効率的に更新するために使用されます。

keyがないと、以下のような警告が表示されます。

Warning: Each child in a list should have a unique "key" prop.

Reactの差分検出とkeyの役割

Reactは仮想DOM(Virtual DOM)を使って、実際のDOMへの変更を最小限に抑えています。配列の要素が変更されたとき、keyがあることで、どの要素が追加・削除・移動されたのかを正確に判断できます。

適切なkeyの選び方

keyには、以下の優先順位で値を選びましょう。

1. 一意のID(推奨)

データベースから取得したIDなど、各要素を一意に識別できる値を使います。

const users = [
  { id: 'u001', name: '田中' },
  { id: 'u002', name: '佐藤' },
];

{users.map((user) => (
  <li key={user.id}>{user.name}</li>
))}

2. インデックス(条件付き)

データに一意のIDがない場合、配列のインデックスを使うこともできます。ただし、以下の条件を満たす場合のみ使用してください。

  • 配列の並び替えが発生しない
  • 要素の追加・削除が発生しない
  • 配列が静的である
const staticList = ['リンゴ', 'バナナ', 'オレンジ'];

{staticList.map((fruit, index) => (
  <li key={index}>{fruit}</li>
))}

よくある間違いとその影響

間違い1: keyを指定しない

// NG: keyがない
{users.map((user) => (
  <li>{user.name}</li>
))}

この場合、Reactは警告を表示し、パフォーマンスが低下する可能性があります。

間違い2: インデックスを不適切に使用

// NG: 並び替えや削除がある場合
{users
  .sort((a, b) => a.name.localeCompare(b.name))
  .map((user, index) => (
    <li key={index}>{user.name}</li>
  ))}

並び替え後もインデックスは0から始まるため、Reactは要素の入れ替わりを正しく検出できません。結果として、予期しない表示やパフォーマンス問題が発生します。

間違い3: ランダムな値を使用

// NG: 毎回異なる値が生成される
{users.map((user) => (
  <li key={Math.random()}>{user.name}</li>
))}

再レンダリングのたびに新しいkeyが生成されるため、Reactは毎回全要素を再作成してしまいます。

どうしてもfor文を使いたい場合

JSX外でfor文を使う方法

JSX内では使えませんが、JSXの外でfor文を使って配列を構築することは可能です。

function UserList() {
  const users = ['田中', '佐藤', '鈴木'];
  const listItems = [];
  
  // JSXの外でfor文を使用
  for (let i = 0; i < users.length; i++) {
    listItems.push(
      <li key={i}>{users[i]}</li>
    );
  }
  
  return <ul>{listItems}</ul>;
}

この方法なら、従来のfor文の構文をそのまま使えます。ただし、多くの場合はmap()を使う方がシンプルで読みやすいコードになります。

for...ofやforEachの活用

for...of文やforEach()メソッドも、JSXの外で使用できます。

for...of文を使う例

function UserList() {
  const users = [
    { id: 1, name: '田中' },
    { id: 2, name: '佐藤' },
    { id: 3, name: '鈴木' }
  ];
  const listItems = [];
  
  for (const user of users) {
    listItems.push(
      <li key={user.id}>{user.name}</li>
    );
  }
  
  return <ul>{listItems}</ul>;
}

forEachを使う例

function UserList() {
  const users = ['田中', '佐藤', '鈴木'];
  const listItems = [];
  
  users.forEach((user, index) => {
    listItems.push(
      <li key={index}>{user}</li>
    );
  });
  
  return <ul>{listItems}</ul>;
}

それぞれの使い分け

以下の表は、各方法の特徴と適している場面をまとめたものです。

方法 特徴 適している場面
map() 式として評価され、新しい配列を返す。JSX内で直接使用可能 ほとんどの繰り返し処理(推奨)
for文 従来の繰り返し構文。JSXの外で使用 複雑な条件分岐や処理が必要な場合
for...of 配列の値を直接取得できる。JSXの外で使用 インデックスが不要な場合
forEach() 配列メソッドとして使用。戻り値なし 副作用を伴う処理(ただしReactでは非推奨)

実際のReact開発では、map()メソッドを使うのが最も一般的で推奨される方法です。コードが簡潔になり、関数型プログラミングの考え方にも合致します。

まとめ

Reactでの繰り返し処理について、重要なポイントをまとめます。

Reactでの繰り返し処理のベストプラクティス

  1. JSX内では式しか使えない

    • for文は文なので、JSXの中括弧内に直接記述できません
    • 式である配列のmap()メソッドを使用しましょう
  2. map()メソッドを使うのが標準

    • JSX内で直接使用できる
    • コードが簡潔で読みやすい
    • Reactの開発スタイルに適している
  3. keyプロパティは必須

    • 繰り返し処理で生成する要素には、必ずkeyを指定する
    • 可能な限り一意のIDを使用する
    • インデックスは、配列が静的な場合のみ使用する
  4. for文も使える

    • JSXの外で配列を構築すれば、for文も使用可能
    • ただし、map()の方がシンプルなケースが多い
0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?