You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@tanstack/react-query刷新页面时出现错误求助

问题分析与解决方案

这个报错的核心原因是Remix的服务端渲染(SSR)和React Query的客户端初始化逻辑不兼容:

  1. 你当前代码里的QueryClient是全局单例,服务端处理多请求时会出现实例复用问题,导致跨请求状态污染。
  2. 刷新子页面时,服务端先渲染组件,但React Query的useQuery在服务端默认不会触发请求,服务端渲染的是Loading...状态;而客户端hydrate时如果直接获取到数据,会导致DOM内容不匹配,进而触发innerHTML相关错误。

修正后的代码示例

1. 在Root路由中处理QueryClient与SSR同步

// app/root.tsx
import {
  QueryClient,
  QueryClientProvider,
  dehydrate,
  Hydrate,
} from "@tanstack/react-query";
import { Outlet, useLoaderData } from "@remix-run/react";

export async function loader() {
  // 为每个请求创建独立的QueryClient实例
  const queryClient = new QueryClient();
  
  // 服务端预取子页面需要的数据,确保服务端渲染内容与客户端一致
  await queryClient.prefetchQuery({
    queryKey: ["repoData"],
    queryFn: () =>
      fetch("https://jsonplaceholder.typicode.com/posts/1").then((res) => res.json()),
  });

  return dehydrate(queryClient);
}

export default function App() {
  const dehydratedState = useLoaderData();
  // 客户端创建新QueryClient,用服务端的脱水状态初始化
  const queryClient = new QueryClient();

  return (
    <html lang="zh-CN">
      <head>
        <title>Remix + React Query</title>
      </head>
      <body>
        <QueryClientProvider client={queryClient}>
          <Hydrate state={dehydratedState}>
            <Outlet />
          </Hydrate>
        </QueryClientProvider>
      </body>
    </html>
  );
}

2. 子页面组件简化(无需再包裹QueryClientProvider)

// app/routes/your-sub-page.tsx
import { useQuery } from "@tanstack/react-query";

export default function Device2ServerFrameParser() {
  return <Example />;
}

function Example() {
  const { isLoading, error, data } = useQuery({
    queryKey: ["repoData"],
    queryFn: () =>
      fetch("https://jsonplaceholder.typicode.com/posts/1").then((res) =>
        res.json()
      ),
  });

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error</div>;

  return (
    <div>
      <span>{JSON.stringify(data)}</span>
    </div>
  );
}

关键调整点

  • 每个请求独立QueryClient:服务端loader内创建实例,避免跨请求状态污染。
  • 服务端预取数据:通过prefetchQuery让服务端提前获取数据,确保服务端渲染内容与客户端hydrate后的内容一致,解决DOM不匹配问题。
  • 使用Hydrate组件:将服务端脱水的状态同步到客户端QueryClient,避免客户端重复请求且保证hydration流程正常。

内容的提问来源于stack exchange,提问作者Gi Tobias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 21:00:23