clientLoader除了(或代替)loader 之外,你还可以定义一个将在客户端执行的 clientLoader 函数。
¥In addition to (or in place of) your loader, you may define a clientLoader function that will execute on the client.
每个路由都可以定义一个 clientLoader 函数,用于在渲染时向路由提供数据:
¥Each route can define a clientLoader function that provides data to the route when rendering:
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;
};
此函数仅在客户端运行,并且可以通过以下几种方式使用:
¥This function is only ever run on the client and can be used in a few ways:
对于全客户端路由,不再使用服务器 loader
¥Instead of a server loader for full-client routes
要通过在变更时使缓存无效来与 clientLoader 缓存一起使用
¥To use alongside a clientLoader cache by invalidating the cache on mutations
要进一步增强从服务器加载的数据
¥To further augment data loaded from the server
例如,从 localStorage 加载用户特定的偏好设置
¥I.e., loading user-specific preferences from localStorage
为了方便从 React Router 迁移
¥To facilitate a migration from React Router
¥Hydration Behavior
默认情况下,在初始 SSR 文档请求中,在 Remix 应用的水合过程中,clientLoader 不会针对路由执行。这适用于主要(且更简单)的用例,其中 clientLoader 不会改变服务器 loader 数据的形状,而只是对后续客户端导航(从缓存读取或直接访问 API)进行优化。
¥By default, clientLoader will not execute for the route during hydration of your Remix app on the initial SSR document request. This is for the primary (and simpler) use-case where the clientLoader does not change the shape of the server loader data and is just an optimization on subsequent client side navigations (to read from a cache or hit an API directly).
export async function loader() {
// During SSR, we talk to the DB directly
const data = getServerDataFromDb();
return json(data);
}
export async function clientLoader() {
// During client-side navigations, we hit our exposed API endpoints directly
const data = await fetchDataFromApi();
return data;
}
export default function Component() {
const data = useLoaderData<typeof loader>();
return <>...</>;
}
clientLoader.hydrate如果你需要在初始文档请求的 hydration 过程中运行 clientLoader,可以通过设置 clientLoader.hydrate=true 来选择加入。这将告诉 Remix 它需要在 Hydration 上运行 clientLoader。如果没有 HydrateFallback,你的路由组件将使用服务器 loader 数据进行 SSR。 - 然后 clientLoader 将运行,返回的数据将在水合路由组件中就地更新。
¥If you need to run your clientLoader during hydration on the initial document request, you can opt in by setting clientLoader.hydrate=true. This will tell Remix that it needs to run the clientLoader on hydration. Without a HydrateFallback, your route component will be SSR'd with the server loader data - and then clientLoader will run and the returned data will be updated in-place in the hydrated route Component.
clientLoader 但没有导出服务器 loader,则 clientLoader.hydrate 会自动被视为 true,因为没有服务器数据可供 SSR 使用。因此,我们始终需要在渲染路由组件之前在 Hydration 上运行 clientLoader。
如果你需要避免在服务器端渲染 (SSR) 期间渲染默认路由组件,因为你的数据必须来自 clientLoader,你可以从路由中导出将在服务器端渲染 (SSR) 期间渲染的 HydrateFallback 组件,并且只有当 clientLoader 在 Hyation 上运行时,你的路由组件才会被渲染。
¥If you need to avoid rendering your default route component during SSR because you have data that must come from a clientLoader, you can export a HydrateFallback component from your route that will be rendered during SSR, and only once the clientLoader runs on hydration will your router component be rendered.
¥Arguments
params¥This function receives the same params argument as a loader.
request¥This function receives the same request argument as a loader.
serverLoaderserverLoader 是一个异步函数,用于从服务器 loader 获取此路由的数据。在客户端导航中,这将对 Remix 服务器 loader 发出 fetch 调用。如果你选择在 Hydration 上运行 clientLoader,那么此函数将返回已在服务器上加载的数据(通过 Promise.resolve)。
¥serverLoader is an asynchronous function to get the data from the server loader for this route. On client-side navigations, this will make a fetch call to the Remix server loader. If you opt-into running your clientLoader on hydration, then this function will return you the data already loaded on the server (via Promise.resolve).
另请参阅:
¥See also: