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
.
serverLoader
serverLoader
是一个异步函数,用于从服务器 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: