react-routerの<Outlet>


Typescript React

例えばメインコンテンツとサイドバーとかだったりとかを描画するときにメインコンテンツだけをreact-routerのパターンマッチによって描画するデータを変えたいみたいな場合には<Outlet />を使うことでできるらしい

一般的にメインデータを描画するところとそうじゃないところを同一のルーティングマッチで描画するのはよくないらしい

ということで使ってみた

index.tsx

<Route>を入れ子にする

import React from 'react';
import { createRoot } from 'react-dom/client';
import { HashRouter, Navigate, Route, Routes } from 'react-router-dom';
import Layout from './components/Layout';
import Sample from './pages/Sample';

const container = document.getElementById('root');

if (container == null) {
  throw new Error('ERROR');
}

const root = createRoot(container);
root.render(
  <React.StrictMode>
    <HashRouter>
      <Routes>
        <Route element={<Layout />}>
          <Route path="/" element={<Navigate to="/sample" replace />} />
          <Route path="/sample" element={<Sample />} />
        </Route>
      </Routes>
    </HashRouter>
  </React.StrictMode>
);

Layout.tsx

import { Outlet } from 'react-router-dom';

const Layout = (): React.JSX.Element => {
  return (
    <main style={{ color: 'red' }}>
      <Outlet />
    </main>
  );
};

export default Layout;

描画するページコンポーネントは省略するが、ルーティングマッチしたコンポーネントが<Outlet />で描画される。

公式: https://react-router-docs-ja.techtalk.jp/api/components/Outlet

余談: Outlet外から値を受け渡すには?

<Outlet />にはpropsがないので単純に値を渡したりpropsリレーしたりすることができないが、context(useOutletContext)を使うとOutlet外からのデータのやりとりとかを利用することができるっぽい

import { Outlet } from 'react-router-dom';

const Layout = (): React.JSX.Element => {
  const data = { message: 'Hello World' };

  return (
    <main style={{ color: 'red' }}>
      <Outlet context={{ data }} />
    </main>
  );
};

export default Layout;
Typescriptの場合はcontextに渡す型をちゃんと渡すこと

あとは以下のような感じでルーティングマッチしたページコンポーネントとかで使用できるみたい

const { data } = useOutletContext<DataOutletType>();
Table of Contents
index.tsx Layout.tsx 余談: Outlet外から値を受け渡すには?
関連記事