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

Next.js构建报错:预渲染页面时React-Query未设置QueryClient的解决方法

解决Next.js构建时React-Query的"No QueryClient set"错误

问题背景

使用Next.js结合React-Query实现用户鉴权的useUser Hook,开发环境运行正常,但执行npm run build时触发预渲染报错:No QueryClient set, use QueryClientProvider to set one,取消index.tsx中useUser相关代码的注释后就会出现该错误。

问题原因

  1. 预渲染阶段缺少QueryClient上下文:Next.js的静态生成(SSG)或服务器端渲染(SSR)过程中,组件在服务器端执行,但全局未通过QueryClientProvider提供QueryClient实例,导致useQuery无法找到所需上下文。
  2. 依赖版本冲突:项目同时安装了旧版react-query@3.x和新版@tanstack/react-query@4.x,两者API和包结构不兼容,引发上下文识别异常。

解决方案

1. 清理依赖冲突

先卸载旧版React Query及对应类型定义,确保仅保留新版@tanstack/react-query:

npm uninstall react-query @types/react-query

后续代码统一使用@tanstack/react-query的v4版本API。

2. 全局配置QueryClientProvider

在Next.js的_app.tsx中包裹整个应用,提供全局的QueryClient实例,同时区分客户端与服务器端实例,避免 hydration 错误:

import { AppProps } from 'next/app';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useState } from 'react';

export default function MyApp({ Component, pageProps }: AppProps) {
  // 仅在客户端初始化QueryClient,防止服务器端重复创建
  const [queryClient] = useState(() => new QueryClient({
    defaultOptions: {
      queries: {
        refetchOnWindowFocus: false, // 根据需求调整缓存策略
        retry: 0,
      },
    },
  }));

  return (
    <QueryClientProvider client={queryClient}>
      <Component {...pageProps} />
    </QueryClientProvider>
  );
}

3. 优化useUser Hook的客户端执行逻辑

修改useUser.tsx,确保查询仅在客户端执行,避免服务器端预渲染时触发错误:

import { useQuery } from '@tanstack/react-query';
import { useState, useEffect } from 'react';
import Router from 'next/router';

interface IParams {
  redirectTo?: string;
  redirectIfFound?: boolean;
}

// 你的鉴权逻辑函数
const isAuthed = async () => {
  const res = await fetch('/api/auth/check');
  return res.json();
};

const useUser = ({ redirectTo, redirectIfFound }: IParams) => {
  const isClient = typeof window !== 'undefined';
  
  // 仅在客户端启用查询,避免服务器端预渲染报错
  const { data, error } = useQuery(["authed"], isAuthed, {
    enabled: isClient,
  });

  const [calledPush, setCalledPush] = useState(false);
  const user = data?.data;
  const hasUser = user;

  useEffect(() => {
    if (!redirectTo || !isClient) return;
    
    if ((redirectTo && !redirectIfFound && !hasUser) || (redirectIfFound && hasUser)) {
      let calledPushLatest;
      setCalledPush((latest) => {
        calledPushLatest = latest;
        return latest;
      });

      if (calledPushLatest) return;

      setCalledPush(true);
      Router.push(redirectTo);
    }
  }, [redirectTo, redirectIfFound, hasUser, isClient]);

  return error ? null : user;
};

export default useUser;

4. 验证构建

执行npm run build,确认报错消失,构建流程正常完成。

内容的提问来源于stack exchange,提问作者김정수

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 14:06:24