lazy
为了保持应用程序包较小并支持路由的代码拆分,每条路由都可以提供一个异步函数,解析路由定义中的非路由匹配部分(loader
、action
、Component/element
、ErrorBoundary/errorElement
等)。
惰性路由在初始加载时以及在导航或提取器调用的加载或提交阶段得到解决。您不能延迟定义路由匹配属性(路径、索引、子项、区分大小写),因为我们只在匹配已知路由后才执行您的延迟路由函数。
每个懒惰函数通常会返回动态导入的结果。
let routes = createRoutesFromElements(
<Route path="/" element={<Layout />}>
<Route path="a" lazy={() => import("./a")} />
<Route path="b" lazy={() => import("./b")} />
</Route>
);
然后在懒惰路由模块中,导出要为路由定义的属性(加载器、组件、ErrorBoundary):
export async function loader({ request }) {
let data = await fetchData(request);
return json(data);
}
export function Component() {
let data = useLoaderData();
return (
<>
<h1>You made it!</h1>
<p>{data}</p>
</>
);
}
// If you want to customize the component display name in React dev tools:
Component.displayName = "SampleLazyRoute";
export function ErrorBoundary() {
let error = useRouteError();
return isRouteErrorResponse(error) ? (
<h1>
{error.status} {error.statusText}
</h1>
) : (
<h1>{error.message || error}</h1>
);
}
// If you want to customize the component display name in React dev tools:
ErrorBoundary.displayName = "SampleErrorBoundary";
请注意,这个延迟加载的文件中没有“默认”导出。这是因为default
不是路由对象上的有效键。这些文件通常只应导出您在路由对象上定义的键,如“loader”、“action”、“Component”、“ErrorBoundary”等。除非您手动从“lazy”返回对象,否则所有导出都将直接在路由对象中展开。
静态定义的属性
在路由上静态定义的任何属性都不能被lazy函数覆盖,如果您尝试覆盖它们,您将收到控制台警告。
此外,作为一种优化,如果你静态地定义了一个加载器/操作,那么它将与懒惰函数并行调用。如果你有轻量级的加载器,你不介意关键的捆绑包,并且想在组件下载的同时启动它们的数据获取,那么这很有用。这与Remix处理获取的方式接近,因为每个路由都是它自己的API路由。
let route = {
path: "projects",
loader: ({ request }) => fetchDataForUrl(request.url),
lazy: () => import("./projects"),
};
这也允许您进行更精细的代码拆分。例如,您可以将加载器和组件拆分为不同的文件进行并行下载:
let route = {
path: "projects",
async loader({ request, params }) {
let { loader } = await import("./projects-loader");
return loader({ request, params });
},
lazy: () => import("./projects-component"),
};
multiple-routes-in-a-single-file
虽然lazy通常可以1:1使用每条路由的异步import(),但您可以自由实现更高级的lazy函数,只需要返回要添加到该路由的属性。这开辟了一些有趣的可能性。
例如,如果你想避免为嵌套路由加载多个块,你可以将它们全部存储在同一个文件中,并将它们返回给各个路由。现代绑定器将为不同的import()调用锁定相同的Promise。
// Assume pages/Dashboard.jsx has all of our loaders/components for multiple
// dashboard routes
let dashboardRoute = {
path: "dashboard",
async lazy() {
let { Layout } = await import("./pages/Dashboard");
return { Component: Layout };
},
children: [
{
index: true,
async lazy() {
let { Index } = await import("./pages/Dashboard");
return { Component: Index };
},
},
{
path: "messages",
async lazy() {
let { messagesLoader, Messages } = await import(
"./pages/Dashboard"
);
return {
loader: messagesLoader,
Component: Messages,
};
},
},
],
};
最后更新于
这有帮助吗?