Skip to content

"No QueryClient set" 错误解决方案

问题描述

在使用 @tanstack/react-query(原 react-query)时,经常会遇到以下错误:

Error: No QueryClient set, use QueryClientProvider to set one

错误截图:Error: No QueryClient set, use QueryClientProvider to set one

这个错误通常出现在尝试使用 useQuery hook 但未正确设置 QueryClientProvider 的情况下。以下是一个触发该错误的典型代码示例:

js
import React from 'react'
import { useQuery } from "react-query";

const fetchPlanets = async () => {
    const result = await fetch('https://swapi.dev/api/people')
    return result.json()
}

const Planets = () => {
    const { data, status } = useQuery('Planets', fetchPlanets)
    console.log("data", data, "status", status)
    return (
        <div>
            <h2>Planets</h2>
        </div>
    )
}

export default Planets

解决方案

基础解决方案:添加 QueryClientProvider

最基本的解决方案是在应用的顶层添加 QueryClientProvider

js
import React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient()

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <YourAppComponent />
    </QueryClientProvider>
  )
}

export default App

创建独立的 Provider 组件

为了避免应用主文件过于臃肿,可以创建一个独立的 Provider 组件:

js
// src/contexts/ReactQueryProvider.tsx
import React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient()

interface Props {
  children: React.ReactNode
}

const ReactQueryProvider: React.FC<Props> = ({ children }) => {
  return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
}

export default ReactQueryProvider

然后在主应用文件中使用:

js
import React from 'react'
import AppRouter from './routers/AppRouter'
import Header from './components/Header'
import ReactQueryProvider from './contexts/ReactQueryProvider'

const App: React.FC = () => {
  return (
    <div className="App">
      <ReactQueryProvider>
        <Header/>
        <AppRouter/>
      </ReactQueryProvider>
    </div>
  )
}

export default App

处理 Provider 嵌套顺序

确保 QueryClientProvider 位于其他自定义 Provider 之上:

js
<QueryClientProvider client={queryClient}>
  <ModalContextProvider>
    {children}
  </ModalContextProvider>
</QueryClientProvider>
js
<ModalContextProvider>
  <QueryClientProvider client={queryClient}>
    {children}
  </QueryClientProvider>
</ModalContextProvider>

版本兼容性问题

注意包名变更

React Query 在版本 4 后更名为 @tanstack/react-query,请确保导入一致性:

  • React Query <= v3: react-query
  • React Query >= v4: @tanstack/react-query

检查并统一项目中的所有导入语句:

js
// 统一使用一种导入方式
import { useQuery } from "@tanstack/react-query";
// 或者(仅适用于 v3 及以下版本)
import { useQuery } from "react-query";

排查重复依赖

使用以下命令检查是否存在重复的依赖:

bash
# 使用 yarn
yarn why react-query
yarn why @tanstack/react-query

# 使用 npm
npm ls react-query
npm ls @tanstack/react-query

如果发现同时存在 react-query@tanstack/react-query,请移除其中一个。

开发工具兼容性

确保开发工具版本与主库版本匹配:

json
// package.json
{
  "dependencies": {
    "@tanstack/react-query": "^4.13.0",
    "@tanstack/react-query-devtools": "^4.13.0"
  }
}

导入方式也需要对应版本:

js
// v4+ 版本的正确导入方式
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

// v3 版本的正确导入方式
import { ReactQueryDevtools } from 'react-query/devtools'

上下文共享设置

在微前端架构或模块联合场景中,启用上下文共享:

js
<QueryClientProvider client={queryClient} contextSharing={true}>
  <App />
</QueryClientProvider>

避免在 Provider 同级使用 Hook

不要在 QueryClientProvider 同级或上级组件中使用 useQuery

js
function App() {
  const { user } = useCurrentUser() // 这里会报错

  return (
    <QueryClientProvider client={queryClient}>
      {/* ... */}
    </QueryClientProvider>
  )
}
js
function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <AppContent />
    </QueryClientProvider>
  )
}

function AppContent() {
  const { user } = useCurrentUser() // 这里可以正常使用
  return /* ... */
}

总结

"No QueryClient set" 错误的主要原因是未正确设置 QueryClientProvider 或存在版本/导入不一致问题。通过以下步骤可以解决大多数情况:

  1. 确保应用被 QueryClientProvider 包裹
  2. 检查并统一所有导入语句
  3. 移除重复的依赖包
  4. 确保开发工具版本匹配
  5. 在复杂场景中启用 contextSharing
  6. 避免在 Provider 同级使用 React Query hooks

遵循这些最佳实践,可以避免这个常见错误并确保 React Query 正常工作。