react-routerの<Outlet>
例えばメインコンテンツとサイドバーとかだったりとかを描画するときにメインコンテンツだけを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>();