HydrateFallback

HydrateFallback

HydrateFallback 组件是一种通知 Remix 你不想在 clientLoader 运行完 Hymtion 之前渲染路由组件的方式。导出时,Remix 将在服务端渲染 (SSR) 期间渲染回退组件,而不是默认路由组件,并在 clientLoader 完成后在客户端渲染路由组件。

¥A HydrateFallback component is your way of informing Remix that you do not want to render your route component until after the clientLoader has run on hydration. When exported, Remix will render the fallback during SSR instead of your default route component, and will render your route component client-side once the clientLoader completes.

最常见的用例是仅客户端路由(例如浏览器内置的 Canvas 游戏)以及使用客户端数据(例如已保存的用户偏好设置)扩充服务器数据。

¥The most common use-cases for this are client-only routes (such as an in-browser canvas game) and augmenting your server data with client-side data (such as saved user preferences).

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} />;
}
export async function loader() {
  const data = getServerData();
  return json(data);
}

export async function clientLoader({
  request,
  params,
  serverLoader,
}: ClientLoaderFunctionArgs) {
  const [serverData, preferences] = await Promise.all([
    serverLoader(),
    getUserPreferences(),
  ]);
  return {
    ...serverData,
    preferences,
  };
}
clientLoader.hydrate = true;

export function HydrateFallback() {
  return <p>Loading user preferences...</p>;
}

export default function Component() {
  const data = useLoaderData<typeof clientLoader>();
  if (data.preferences.display === "list") {
    return <ListView items={data.items} />;
  } else {
    return <GridView items={data.items} />;
  }
}

关于 HydrateFallback 的行为,有几个细微差别值得注意:

¥There are a few nuances worth noting around the behavior of HydrateFallback:

  • 它仅与初始文档请求和 hydration 相关,不会在任何后续的客户端导航中渲染。

    ¥It is only relevant on initial document request and hydration and will not be rendered on any subsequent client-side navigations

  • 仅当你在给定路由上设置 clientLoader.hydrate=true 时,它才相关。

    ¥It is only relevant when you are also setting clientLoader.hydrate=true on a given route

  • 如果你的 clientLoader 没有服务器 loader,这也很重要,因为这意味着 clientLoader.hydrate=true,否则 useLoaderData 根本没有返回任何加载器数据。

    ¥It is also relevant if you do have a clientLoader without a server loader, as this implies clientLoader.hydrate=true since there is otherwise no loader data at all to return from useLoaderData

    • 即使你在这种情况下未指定 HydrateFallback,Remix 也不会渲染你的路由组件,并且会向上冒泡到任何祖级 HydrateFallback 组件。

      ¥Even if you do not specify a HydrateFallback in this case, Remix will not render your route component and will bubble up to any ancestor HydrateFallback component

    • 这是为了确保 useLoaderData 仍然是 "happy-path"。

      ¥This is to ensure that useLoaderData remains "happy-path"

    • 如果没有服务器 loaderuseLoaderData 将在渲染的任何路由组件中返回 undefined

      ¥Without a server loader, useLoaderData would return undefined in any rendered route components

  • 你无法在 HydrateFallback 中渲染 <Outlet/>,因为如果子路由在 Hydration 中运行 clientLoader 函数(例如 useRouteLoaderData()useMatches() 等用例),则无法保证其祖级加载器数据正常运行。

    ¥You cannot render an <Outlet/> in a HydrateFallback because children routes can't be guaranteed to operate correctly since their ancestor loader data may not yet be available if they are running clientLoader functions on hydration (i.e., use cases such as useRouteLoaderData() or useMatches())

另请参阅:

¥See also:

Remix v2.17 中文网 - 粤ICP备13048890号