Remix 学习 - 路由模块(Route Module)
在 Remix 中,每个路由模块(Route Module)都可以包含多个导出,用于处理不同的功能。以下是每个路由模块主要的导出内容:
1. Component
-
默认导出:每个路由模块通常会默认导出一个 React 组件。这是用于渲染该路由的页面。
export default function MyPage() { return <h1>Hello, Remix!</h1>; }
2. Loader
- 数据加载:
loader
函数用于在服务器端获取数据。它返回的数据可以在组件中使用。import { json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; export async function loader() { return json({ name: "Ryan", date: new Date() }); } export default function SomeRoute() { const data = useLoaderData<typeof loader>(); }
- 此函数仅在服务器上运行。在初始服务器渲染时,它将向 HTML 文档提供数据。在浏览器中导航时,Remix 将通过fetch浏览器调用该函数。
- 这意味着您可以直接与数据库对话,使用仅限服务器的 API 机密等。任何未用于呈现 UI 的代码都将从浏览器包中删除。
3. Action
- 表单提交:
action
函数用于处理表单提交和其他POST
请求。export async function action({ request }) { const formData = await request.formData(); await saveData(formData); return redirect('/success'); }
- 路由
action
是服务器唯一功能,用于处理数据变化和其他操作。 - 如果对路由发出非
GET
请求(DELETE
、PATCH
、POST
或PUT
),则在loader
之前调用action
。
4. Meta
-
元数据:
meta
函数用于定义页面的元数据,如标题和描述。export const meta: MetaFunction = () => { return [ { title: "Very cool app | Remix" }, { property: "og:title", content: "Very cool app", }, { name: "description", content: "This app is the best", }, ]; };
生成如下 HTML:
<title>Very cool app | Remix</title> <meta property="og:title" content="Very cool app" />; <meta name="description" content="This app is the best" />
5. Links
-
样式和链接:
links
函数用于加载 CSS 或链接其他资源。import type { LinksFunction } from "@remix-run/node"; // or cloudflare/deno export const links: LinksFunction = () => { return [ { rel: "icon", href: "/favicon.png", type: "image/png", }, { rel: "stylesheet", href: "https://example.com/some/styles.css", }, { page: "/users/123" }, { rel: "preload", href: "/images/banner.jpg", as: "image", }, ]; };
6. ErrorBoundary
-
错误处理:用于捕获未处理的 JavaScript 错误,并提供错误信息。
import { isRouteErrorResponse, useRouteError } from "@remix-run/react"; 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>; } }
7. CatchBoundary
-
特定错误处理:用于处理特定 HTTP 错误,如 404。
export function CatchBoundary() { let caught = useCatch(); return ( <div> <h1>Error {caught.status}</h1> <p>{caught.statusText}</p> </div> ); }
8. Client Loader (clientLoader
)
- 客户端数据加载:用于在客户端进行数据加载,适合在页面交互后需要动态更新的数据。
- 返回的数据用于客户端更新,不影响初始服务器端渲染。
- 可以提供更好的用户体验,因为它避免了不必要的页面刷新和服务器负载。
export const clientLoader = async ({ request, params, serverLoader, }: ClientLoaderFunctionArgs) => { // 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; };
9. Client Action (clientAction
)
- 客户端表单处理:在客户端处理表单提交,用于无刷新提交,无需与服务器交互。
export const clientAction = async ({ request, params, serverAction, }: ClientActionFunctionArgs) => { invalidateClientSideCache(); const data = await serverAction(); return data; };
10. Handle
-
路由元数据:用于传递自定义数据或配置到路由模块,比如页面标题、描述等,供其他部分(如布局组件、文档组件)使用。
// 在路由模块中 export let handle = { breadcrumb: 'Home', customData: { someKey: 'someValue' } }; // 在其他地方使用 handle 数据 export default function SomeRoute() { let data = useLoaderData(); let handle = useRouteHandle(); return ( <div> <h1>{handle.breadcrumb}</h1> <p>{data.someData}</p> </div> ); }
11. Headers
-
自定义头部:定义页面的 HTTP 头部信息。
import type { HeadersFunction } from "@remix-run/node"; // or cloudflare/deno export const headers: HeadersFunction = ({ actionHeaders, errorHeaders, loaderHeaders, parentHeaders, }) => ({ "X-Stretchy-Pants": "its for fun", "Cache-Control": "max-age=300, s-maxage=3600", });
12. HydrateFallback
- 加载占位符:用于在客户端渲染之前显示的占位内容。
export async function clientLoader() { const data = await loadSavedGameOrPrepareNewGame(); return data; } // Note clientLoader.hydrate is implied without a server loader export function HydrateFallback() { return <p>Loading Game...</p>; } export default function Component() { const data = useLoaderData<typeof clientLoader>(); return <Game data={data} />; }
13. Should Revalidate (shouldRevalidate
)
-
重新验证:控制数据是否需要重新验证或刷新。
-
此功能可让应用程序优化在
actions
以及客户端导航后,判断应重新加载哪些路由数据。import type { ShouldRevalidateFunction } from "@remix-run/react"; export const shouldRevalidate: ShouldRevalidateFunction = ({ actionResult, currentParams, currentUrl, defaultShouldRevalidate, formAction, formData, formEncType, formMethod, nextParams, nextUrl, }) => { return true; };
每个路由模块可以根据需要导出这些功能,以支持页面的不同需求。通过这些导出,Remix 提供了灵活的方式来处理数据、错误和页面渲染。