React Routerでページタイトルをloaderのデータにする方法
React Router v7にて、「loaderで取得したデータ」を使って「ページタイトル」を設定する方法を解説します。
設定方法
metaのdata
から受け取って、titleに設定します。meta
の引数の型はRoute.MetaArgs
にすると型情報を持ってこれます。
import type { Route } from "./+types/home";import type { LoaderFunctionArgs } from "react-router";
export const loader = async ({ params }: LoaderFunctionArgs) => { // 取得ロジックなど return { name };};
export const meta = ({ data }: Route.MetaArgs) => { return [ { title: data.name }, { name: "description", content: `${data.name}ページです。` }, ];};
+types/〇〇 とは?
前述のimportしている./+types/〇〇
は.react-router/types
ディレクトリ内に生成されるファイルです。
たとえばnpx create-react-router@latest
のテンプレートの場合、.react-router/types
は次のようになります。
├── +future.ts├── +routes.ts├── +server-build.d.ts└── app ├── +types │ └── root.ts └── routes └── +types └── home.ts
この.react-router/types
はreact-router dev
(npm run dev
などの実体)で生成されるようです。明示的に作りたいならreact-router typegen
を叩きましょう。
公式ドキュメント:Type Safety | React Router
+types/〇〇 はどこに対して相対的?
「./+types/〇〇
の./
の部分はどこに対して相対的なんだ」「app/routes
には+types
ディレクトリなんて無いぞ」と思うかもしれません。
ここでtsconfig.json
を見てみましょう。
{ // ... "compilerOptions": { "rootDirs": [ ".", "./.react-router/types" ], // ... }}
rootDirs
に.
と.react-router/types
の2つが設定されています。これによって、app/routes
だけではなく.react-router/types/app/routes
からもimport先を探すようになっています。
新しいファイルでRoute型を使いたい場合
新しくルートのファイルを追加するときにRoute
型を使いたい場合は次のような流れです。まずはファイルを作ります。
// まだRoute型は生成されない
続いてapp/routes.ts
に追加します。この時点でreact-router dev
を実行していれば(すれば)型が生成されます。
import { type RouteConfig, index, route } from "@react-router/dev/routes";
export default [ index("routes/home.tsx"), route("/piyo","routes/piyo/piyo.tsx")] satisfies RouteConfig;
.react-router/types
は次のようになります。
.react-router/types├── ...└── app ├── ... └── routes ├── +types │ └── home.ts └── piyo └── +types └── piyo.ts
新しく追加するルートファイルには+types/piyo
でRoute
型が取れます。
import type { Route } from "./+types/piyo";
別の方法
meta
自体にMetaFunction<typeof loader>
という型を付ける方法もあります。
import type { LoaderFunctionArgs, MetaFunction } from "react-router";
export const loader = async ({ params }: LoaderFunctionArgs) => { // 取得ロジックなど return { name };};
export const meta: MetaFunction<typeof loader> = ({ data }) => { return [ { title: data.name }, { name: "description", content: `${data.name}ページです。` }, ];};
ページタイトルにサイト名を入れたい場合
ページ名 | サイト名
のようにページタイトルの後ろにサイト名を入れたい場合、自分でformatするユーティリティ関数を作り、こいつを使いまわします。
export const SITE_NAME = "サイト名";
export function formatTitle(pageTitle: string) { return `${pageTitle} | ${SITE_NAME}`;}
import { formatTitle } from "./utils"
const pageName = "テスト";export function meta() { return [ { title: formatTitle(pageName) }, { name: "description", content: `${pageName}ページです。` }, ];}
noindexとかもmetaで設定
ついでに。お問い合わせページとかだけnoindexにしたいときもmetaタグなのでmetaに書きます。
const pageName = "お問い合わせ";export function meta() { return [ { title: pageName }, { name: "description", content: `${pageName}ページです。` }, { name: "robots", content: "noindex" }, ];}
公式ドキュメント集
以上、React Router v7におけるページタイトルの設定方法でした。