React Router の Outlet について

React Router の Outlet がなんとなく直感的でなかったので調べました。

公式ドキュメントに基づいて説明します。

サンプルは以下です。

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>

      {/* This element will render either <DashboardMessages> when the URL is
          "/messages", <DashboardTasks> at "/tasks", or null if it is "/"
      */}
      <Outlet />
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Dashboard />}>
        <Route
          path="messages"
          element={<DashboardMessages />}
        />
        <Route path="tasks" element={<DashboardTasks />} />
      </Route>
    </Routes>
  );
}

まず App コンポーネントをみます。

ルーティングが書かれています。以下のことがわかります。

  • URLが / の場合は Dashboard コンポーネントを描画する。
  • URL が /messages の場合は Dashboard コンポーネントを描画して、その中でDashboardMessages コンポーネントを描画する。
  • URL が /tasks の場合は Dashboard コンポーネントを描画して、その中でDashboardTasks をコンポーネントを描画する。
  • DashboardMessages と DashboardTasks は Dashboard の子コンポーネントである。

次に Dashboard コンポーネントをみます。

Dashboard コンポーネントはシンプルで、以下を描画します。

  • div
  • h1
  • Outletコンポーネント

div と h1 は必ず描画されます。

そして Outlet コンポーネントが何に対応するかというと、先ほどのルーティングの以下の部分です。

        <Route
          path="messages"
          element={<DashboardMessages />}
        />
        <Route path="tasks" element={<DashboardTasks />} />

つまり、Outlet の部分を置き換えると以下と同じイメージになります。

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>

      {/* Outletの部分は実際に以下のようなイメージ*/}
      <Routes>
        <Route
            path="messages"
            element={<DashboardMessages />}
          />
          <Route path="tasks" element={<DashboardTasks />} />
      </Routes>
    </div>
  );
}

Dashboard コンポーネント内のルーティングがそのまま描画されるイメージです。

Outletを使うと何が嬉しいかというと、一番上のサンプルのように App コンポーネントにルーティングの全体像をかけることです。

これは別にAppコンポーネントに書かなくても問題ありません。

要は、そのアプリケーションの全体のルーティングを一箇所にかけるので、見通しが良くなります。

Outlet を使わない場合は、最後のサンプルのように各コンポーネントファイルに書かなくてはいけないので、ルーティングがある部分が各ファイルに分散してしまうのです。