为 TanStack Query 发布状态页的三种方式
选择所需的控制级别 — 零代码、低代码或完全 headless。
托管
添加 TanStack Query 端点,把 CNAME 指向 status.yourdomain.com,完成。5 分钟搞定。
嵌入式徽章
将 SVG 正常运行时间和状态徽章放入 README 或落地页。每 5 分钟自动更新。
把这个 health 端点加入你的 TanStack Query 应用
复制、粘贴、把 PulseAPI 指向 URL。健康时返回 200,降级时返回 503。
import { useQuery } from '@tanstack/react-query'
interface StatusData {
page: { title: string; customDomain: string | null }
overallStatus: 'operational' | 'degraded' | 'down' | 'maintenance' | 'unknown'
endpoints: Array<{
id: string
name: string
status: string
uptime24h: number
avgResponseTime: number
}>
}
export const useStatusQuery = (slug: string) =>
useQuery<StatusData>({
queryKey: ['status', slug],
queryFn: async () => {
const r = await fetch(`https://api.pulseapi.tech/status/${slug}`)
if (!r.ok) throw new Error(`Status ${r.status}`)
return r.json()
},
staleTime: 30_000,
refetchInterval: 30_000,
refetchOnWindowFocus: true,
})将 staleTime 和 refetchInterval 设置为 30 秒以匹配我们的 SSE 心跳。若想无轮询实现实时更新,将此 Hook 与 /sse/status/:slug 流结合,并在事件到达时用 queryClient.setQueryData 更新缓存。
TanStack Query 应用会出什么故障 — 如何捕获
长时间打开的标签页状态过期
放置整夜的仪表板可能仍显示绿色横幅,而生产实际已宕机。refetchInterval + refetchOnWindowFocus 让缓存保持真实。
重新验证时出现错误内容闪烁
placeholderData + keepPreviousData 可在重取期间继续显示上次良好状态,避免 "operational" 与加载骨架之间闪烁。
嵌套组件导致过多并行请求
多个组件调用 useStatusQuery 本会各自发请求,但 React Query 根据 queryKey 去重,每个 slug 同时只会有一个 in-flight 请求。
不喜欢我们的状态页? 用 TanStack Query 自己构建。
我们的 API 返回的数据与托管 UI 完全一致。完整 OpenAPI 规范见 api.pulseapi.tech/docs.
import { useStatusQuery } from './use-status-query'
export function StatusBanner({ slug }: { slug: string }) {
const { data, isLoading, error } = useStatusQuery(slug)
if (isLoading) return <div className="skeleton" />
if (error) return null
if (!data) return null
if (data.overallStatus === 'operational') return null
return (
<a href={`https://${data.page.customDomain}`} className="banner">
{data.overallStatus === 'down' ? 'Service disruption' : 'Degraded service'}
{' — '}
{data.endpoints.filter((e) => e.status !== 'operational').length} affected
</a>
)
}TanStack Query 监控 — FAQ
如何将 useQuery 与 SSE 组合以获得实时更新?
在 useEffect 中打开指向 /sse/status/:slug 的 EventSource,每次事件调用 queryClient.setQueryData(["status", slug], to merge event patches into the existing cache entry。useQuery 订阅者无需轮询即保持最新。
支持 TanStack Query v4 和 v5 吗?
都支持。v4 用 cacheTime,v5 改名为 gcTime。v5 的 isLoading 仅表示 "首次加载";若需任意 in-flight 指示请用 isPending + isFetching。
能用 Next.js 或 Remix 在服务端预取状态吗?
可以。在服务器组件或 loader 中调用 queryClient.prefetchQuery,用 HydrationBoundary (v5) 或 Hydrate (v4) 包裹树并传入 dehydrated state。useStatusQuery Hook 首次渲染从 hydrated 缓存读取,客户端无闪烁。
在 useQuery 中使用组织 API key 安全吗?
不安全 — 任何出现在浏览器 JS 的 key 都是公开的。公共状态端点不需要认证;组织 API key 只在服务器使用。如需认证,通过后端路由 (/api/status) 代理,然后从 useQuery 调用该代理。