在 routes.ts
中引用的文件称为路由模块。
route("teams/:teamId", "./team.tsx"),
// route module ^^^^^^^^
路由模块是 React Router 框架功能的基础,它们定义了
本指南简要概述了每个路由模块的功能。入门指南的其余部分将更详细地介绍这些功能。
default
)定义当路由匹配时将渲染的组件。
export default function MyRouteComponent() {
return (
<div>
<h1>Look ma!</h1>
<p>
I'm still using React Router after like 10 years.
</p>
</div>
);
}
loader
路由加载器在渲染路由组件之前为其提供数据。它们仅在服务器端渲染或使用预渲染进行构建时在服务器上调用。
export async function loader() {
return { message: "Hello, world!" };
}
export default function MyRoute({ loaderData }) {
return <h1>{loaderData.message}</h1>;
}
另请参阅
clientLoader
仅在浏览器中调用,路由客户端加载器除了路由加载器之外,还为路由组件提供数据,或替代路由加载器提供数据。
export async function clientLoader({ serverLoader }) {
// call the server loader
const serverData = await serverLoader();
// And/or fetch data on the client
const data = getDataFromClient();
// Return the data to expose through useLoaderData()
return data;
}
客户端加载器可以通过在函数上设置hydrate
属性来参与服务器渲染页面的初始页面加载水合。
export async function clientLoader() {
// ...
}
clientLoader.hydrate = true as const;
通过使用as const
,TypeScript 将推断clientLoader.hydrate
的类型为true
而不是boolean
。这样,React Router 就可以根据clientLoader.hydrate
的值推导出loaderData
的类型。
另请参阅
action
路由操作允许服务器端数据变异,并在从<Form>
、useFetcher
和useSubmit
调用时自动重新验证页面上的所有加载器数据。
// route("/list", "./list.tsx")
import { Form } from "react-router";
import { TodoList } from "~/components/TodoList";
// this data will be loaded after the action completes...
export async function loader() {
const items = await fakeDb.getItems();
return { items };
}
// ...so that the list here is updated automatically
export default function Items({ loaderData }) {
return (
<div>
<List items={loaderData.items} />
<Form method="post" navigate={false} action="/list">
<input type="text" name="title" />
<button type="submit">Create Todo</button>
</Form>
</div>
);
}
export async function action({ request }) {
const data = await request.formData();
const todo = await fakeDb.addItem({
title: data.get("title"),
});
return { ok: true };
}
clientAction
类似于路由操作,但仅在浏览器中调用。
export async function clientAction({ serverAction }) {
fakeInvalidateClientSideCache();
// can still call the server action if needed
const data = await serverAction();
return data;
}
另请参阅
ErrorBoundary
当其他路由模块 API 抛出异常时,将渲染路由模块的ErrorBoundary
而不是路由组件。
import {
isRouteErrorResponse,
useRouteError,
} from "react-router";
export function ErrorBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error)) {
return (
<div>
<h1>
{error.status} {error.statusText}
</h1>
<p>{error.data}</p>
</div>
);
} else if (error instanceof Error) {
return (
<div>
<h1>Error</h1>
<p>{error.message}</p>
<p>The stack trace is:</p>
<pre>{error.stack}</pre>
</div>
);
} else {
return <h1>Unknown Error</h1>;
}
}
HydrateFallback
在初始页面加载时,只有在客户端加载器完成之后才会渲染路由组件。如果导出,HydrateFallback
可以立即渲染在路由组件的位置。
export async function clientLoader() {
const data = await fakeLoadLocalGameData();
return data;
}
export function HydrateFallback() {
return <p>Loading Game...</p>;
}
export default function Component({ loaderData }) {
return <Game data={loaderData} />;
}
headers
路由头定义在服务器渲染时要与响应一起发送的 HTTP 头。
export function headers() {
return {
"X-Stretchy-Pants": "its for fun",
"Cache-Control": "max-age=300, s-maxage=3600",
};
}
handle
路由处理程序允许应用程序在useMatches
中向路由匹配添加任何内容以创建抽象(如面包屑等)。
export const handle = {
its: "all yours",
};
links
路由链接定义要在文档<head>
中渲染的<link>
元素。
export function links() {
return [
{
rel: "icon",
href: "/favicon.png",
type: "image/png",
},
{
rel: "stylesheet",
href: "https://example.com/some/styles.css",
},
{
rel: "preload",
href: "/images/banner.jpg",
as: "image",
},
];
}
所有路由链接都将被聚合并通过<Links />
组件渲染,通常在您的应用程序根目录中渲染。
import { Links } from "react-router";
export default function Root() {
return (
<html>
<head>
<Links />
</head>
<body />
</html>
);
}
meta
路由元数据定义要在文档的<head>
中渲染的元标记。
export function meta() {
return [
{ title: "Very cool app" },
{
property: "og:title",
content: "Very cool app",
},
{
name: "description",
content: "This app is the best",
},
];
}
所有路由的元数据都将被聚合并通过<Meta />
组件渲染,通常在您的应用程序根目录中渲染。
import { Meta } from "react-router";
export default function Root() {
return (
<html>
<head>
<Meta />
</head>
<body />
</html>
);
}
另请参阅
shouldRevalidate
默认情况下,所有路由在操作后都会重新验证。此函数允许路由选择退出不会影响其数据的操作的重新验证。
import type { ShouldRevalidateFunctionArgs } from "react-router";
export function shouldRevalidate(
arg: ShouldRevalidateFunctionArgs
) {
return true;
}
下一步:渲染策略