ReactのFragmentとは?短縮記法との違いを理解しよう

ReactのFragmentとは?

Reactでは、複数の要素をまとめて返したいことがあります。

そんなときに使えるのがFragmentです。 Fragmentを使うと、不要なHTML要素を追加せずに、複数の要素をまとめることができます。

function App() {
  return (
    <>
      <h2>Reactを勉強しよう</h2>
      <p>まずは基本から始めます。</p>
    </>
  );
}

export default App;

この<>...</>が、Fragmentの短縮記法です。

スポンサーリンク

なぜFragmentが必要なの?

まず、次のように複数の要素をそのまま並べて返そうとしてみます。

function App() {
  return (
    <h2>Reactを勉強しよう</h2>
    <p>まずは基本から始めます。</p>
  );
}

export default App;

JSXでは、このように複数の要素をそのまま並べて返すことはできません。 1つにまとめる必要があります。

そこで、divで囲むこともできます。

function App() {
  return (
    <div>
      <h2>Reactを勉強しよう</h2>
      <p>まずは基本から始めます。</p>
    </div>
  );
}

export default App;

この書き方なら問題なく表示できます。 ただし、複数の要素をまとめるためだけにdivを使うと、そのdivもHTMLとして出力されます。

divで複数の要素を囲んだときのElementsパネル
h2pを囲むdivが、HTMLにも追加されています。

余計なdivが入ると、HTMLの構造を保ちたい場面や、CSSで親要素と子要素の関係を使ってレイアウトする場面で扱いにくくなることがあります。

「まとめたいだけで、HTML要素は増やしたくない」という場合にFragmentを使います。

Fragmentを使ってみよう

先ほどのdivをFragmentの短縮記法に置き換えてみます。

function App() {
  return (
    <>
      <h2>Reactを勉強しよう</h2>
      <p>まずは基本から始めます。</p>
    </>
  );
}

export default App;

見た目はdivで囲んだ場合と同じですが、Fragment自体はHTML要素として出力されません。

ブラウザの開発者ツールでElementsを見ると、h2pを囲むためだけの要素が追加されていないことを確認できます。

Fragmentで複数の要素をまとめたときのElementsパネル
Fragment自体はHTMLに追加されず、h2pがそのまま並んでいます。

短縮記法<>...</>とは?

Fragmentには、次の2つの書き方があります。

短縮記法

<>
  <h2>Reactを勉強しよう</h2>
  <p>まずは基本から始めます。</p>
</>

通常は、この<>...</>という短縮記法を使えば十分です。 Fragmentをimportする必要もありません。

Fragmentと書く方法

import { Fragment } from "react";

function App() {
  return (
    <Fragment>
      <h2>Reactを勉強しよう</h2>
      <p>まずは基本から始めます。</p>
    </Fragment>
  );
}

export default App;

こちらも役割は同じです。 Fragmentと明示して書く場合は、Reactからimportします。

既存のコードでは、<React.Fragment>と書かれていることもあります。 これも同じFragmentです。

keyを付けるときはFragmentを使う

短縮記法<>...</>では、keyを指定できません。

たとえば、用語と説明をdlで一覧表示すると、1件のデータからdtddの2つの要素を返すことになります。 このように、map()の中で複数の要素をまとめたい場合にFragmentを使えます。

import { Fragment } from "react";

const items = [
  {
    id: 1,
    term: "React",
    description: "UIを作るためのライブラリ",
  },
  {
    id: 2,
    term: "JSX",
    description: "JavaScriptで使えるHTML風の構文",
  },
];

function App() {
  return (
    <dl>
      {items.map((item) => (
        <Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </Fragment>
      ))}
    </dl>
  );
}

export default App;

このようにkeyが必要な場合は、短縮記法ではなく、 <Fragment key={...}>の形で記述します。

divとFragmentはどう使い分ける?

Fragmentは便利ですが、divをすべてFragmentに置き換えればよいわけではありません。

divそのものに役割がある場合は、divを使います。

<div className="card">
  <h2>React</h2>
  <p>学習中</p>
</div>

この例では、divがカード全体を表す要素として使われています。 CSSを適用するためのまとまりとしても意味があります。

一方、単にJSXを1つにまとめるためだけに囲んでいるなら、Fragmentを使うことを検討できます。

Fragment自体はHTML要素ではないため、classNamestyleを指定して、 Fragmentそのものにスタイルを適用することはできません。

CSSを適用するためのまとまりが必要ならdivなどのHTML要素を使い、 HTML要素を増やさずにJSXだけまとめたいならFragmentを使います。

よくある勘違い

FragmentはHTMLに出力される?

いいえ。 Fragmentは複数の要素をまとめるために使いますが、Fragment自体がHTML要素として追加されるわけではありません。

複数の要素を返すときは、必ずFragmentを使う?

いいえ。 divなど、HTMLとして必要な親要素があるなら、その要素でまとめて問題ありません。 Fragmentは、まとめるためだけの不要なHTML要素を追加したくないときに使います。

短縮記法とFragmentは別の機能?

いいえ。 <>...</>はFragmentの短縮記法です。 基本的な役割は同じですが、短縮記法にはkeyを指定できません。

FragmentにclassNameを付けられる?

divのようにclassNamestyleを指定して、 Fragment自体にスタイルを適用することはできません。 スタイルを適用するためのHTML要素が必要なら、divなどを使いましょう。

まとめ

Fragmentは、不要なHTML要素を追加せずに、複数の要素をまとめるための仕組みです。

  • JSXで複数の要素を返すときは、1つにまとめる必要がある
  • まとめるためだけのHTML要素を増やしたくない場合はFragmentを使える
  • 通常は短縮記法<>...</>を使えばよい
  • keyを指定するときは<Fragment>を使う
  • HTMLとして意味のある親要素が必要なら、divなどを使う

「複数の要素をまとめたい。でも、そのためだけのHTML要素は増やしたくない」というときにFragmentを使うと覚えておきましょう。

スポンサーリンク