Remix 很重视“网络感知 UI”。
因为 Web 不是本地内存操作,而是真正在走网络、走服务器、走数据库。
#页面级 pending:useNavigation
import { Outlet, useNavigation } from "@remix-run/react";
export default function RootLayout() {
const navigation = useNavigation();
const isNavigating = Boolean(navigation.location);
return (
<>
{isNavigating && <div className="global-loading">船只靠港中...</div>}
<Outlet />
</>
);
}#局部 pending:fetcher.state
const fetcher = useFetcher();
<button type="submit" disabled={fetcher.state !== "idle"}>
{fetcher.state === "submitting" ? "提交中..." : "提交"}
</button>#Optimistic UI:先在屏幕上预演结果
function StatusToggle({ ship }: { ship: { id: string; status: string } }) {
const fetcher = useFetcher();
const optimisticStatus =
fetcher.formData?.get("status")?.toString() ?? ship.status;
return (
<fetcher.Form method="post" action={`/ships/${ship.id}/status`}>
<p>状态:{optimisticStatus}</p>
<button name="status" value="arrived">切换为已到港</button>
<button name="status" value="departed">切换为已离港</button>
</fetcher.Form>
);
}Remix 的 pending UI 心智很成熟:
- 不确定结果,就显示忙碌态
- 结果可预测,就做 optimistic UI
- 首屏关键数据先到,次要数据可 skeleton / defer
也就是说,Remix 并不是让你“隐藏网络”,而是让你诚实又顺滑地表达网络正在发生什么。