HydrateFallback

HydrateFallback

HydrateFallback 组件用于通知 Remix,在客户端加载器 (clientLoader) 在水合后完成运行 *之后* 再渲染路由组件。导出时,Remix 将在服务器端渲染 (SSR) 期间渲染回退组件,而不是默认的路由组件,并在客户端加载器完成之后客户端渲染路由组件。

最常见的用例包括仅客户端路由(例如浏览器内的画布游戏)以及使用客户端数据增强服务器数据(例如保存的用户偏好设置)。

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 的行为,有一些细微差别需要注意。

  • 它仅在初始文档请求和水合时相关,在后续的任何客户端导航中都不会渲染。
  • 只有在您也为给定路由设置了 clientLoader.hydrate=true 时,它才相关。
  • 如果您确实有一个 clientLoader 而没有服务器 loader,它也相关,因为这意味着 clientLoader.hydrate=true,因为否则从 useLoaderData 返回的加载器数据根本不存在。
    • 即使在这种情况下您没有指定 HydrateFallback,Remix 也不会渲染您的路由组件,并且会冒泡到任何祖先 HydrateFallback 组件。
    • 这是为了确保 useLoaderData 保持“快乐路径”。
    • 如果没有服务器 loaderuseLoaderData 将在任何渲染的路由组件中返回 undefined
  • 您不能在 HydrateFallback 中渲染 <Outlet/>,因为如果子路由在水合时运行 clientLoader 函数(例如 useRouteLoaderData()useMatches()),则无法保证它们的祖先加载器数据是否可用,因此无法保证子路由能够正常工作。

另请参阅

文档和示例根据以下许可证授权 MIT