React Query 内部:到底发生了什么

31 阅读4分钟

React Query 不仅仅是 hooks,它还是一个数据编排引擎。如果把它当成 hooks,最终会导致重复获取数据、状态过期,以及组件像在 Espresso 上一样重新渲染。

让我们一步一步地了解 React Query,展示每个部分的作用,以及为什么理解它会让您成为更强大的 React 开发人员。

QueryClient — 数据管弦乐队的指挥 显示查询客户端

1- QueryClient 不仅仅是传递给 QueryClientProvider 的道具。

它是整个数据获取管弦乐队的指挥——协调所有查询、管理缓存并确保一切保持同步的唯一事实来源。

2- 为什么 QueryClient 必须稳定? 关键在于:QueryClient它持有QueryCache实例。创建多个QueryClient实例时,实际上是在创建多个相互隔离的缓存。这违背了 React Query 共享状态管理的基本承诺。

// ❌ WRONG: Creates new client on every render function App() { // New instance every render! mean new cashe instance const queryClient = new QueryClient()

return ( ) }

// ✅ CORRECT: Stable reference outside component const queryClient = new QueryClient()

function App() { return ( ) }

// ✅ ALSO CORRECT: Stable reference with useState function App() { const [queryClient] = useState(() => new QueryClient())

return ( ) }` QueryCache——您的内存数据仓库 显示查询缓存

是QueryCacheReact Query 的内存数据仓库——一个 JavaScript 对象,其中的键是您的稳定序列化版本queryKey(称为queryKeyHash),值是Query包含您的实际数据的类实例。

// it is just to simplified the idea

// The Simple Truth: It's Just an Object // Simplified QueryCache structure const queryCache = { // queryKeyHash: Query instance '["users",1]': QueryInstance1, '["posts","published"]': QueryInstance2, '["user",1,"profile"]': QueryInstance3, }

// Where each Query instance contains: class Query { constructor() { this.data = undefined // Your actual data this.error = undefined // Any errors this.status = 'idle' // idle, loading, success, error this.dataUpdatedAt = Date.now() this.errorUpdatedAt = undefined this.staleTime = 0 // ... more metadata } } 查询——具有选择性观察者的智能数据管理器 显示查询

类Query是 React Query 中所有神奇之处的源头。它不仅仅是一个数据容器,更是一个复杂的状态机,可以管理数据获取、重试、取消、去重,最重要的是,它能够准确地知道谁在观看以及他们关注什么。

核心洞察:选择性观察者通知 以上是你提到的关键概念:Query 知道谁订阅了,以及每个订阅者关注的内容。这使得 React Query 能够高效地仅通知观察者他们真正关心的变化。

// Component A: Only cares about loading state function LoadingIndicator() { const { isLoading } = useQuery({ queryKey: ['user', 1], queryFn: fetchUser })

// This component ONLY gets notified when isLoading changes // It doesn't care about data, error, or any other state }

// Component B: Only cares about error state
function ErrorBoundary() { const { isError } = useQuery({ queryKey: ['user', 1], queryFn: fetchUser })

// This component ONLY gets notified when isError changes // It doesn't care about loading, data, or any other state }

// Component C: Only cares about data function UserProfile() { const { data } = useQuery({ queryKey: ['user', 1], queryFn: fetchUser })

// This component ONLY gets notified when data changes // It doesn't care about loading, error, or any other state } QueryObserver — 组件和 QueryCache 之间的智能桥梁 显示查询观察者

是QueryObserver连接你的 React 组件和 的智能桥梁QueryCache。你可以把它想象成一个智能订阅服务,它准确地知道你的组件关注什么,并且只在这些特定的事情发生变化时通知它。

核心概念:智能订阅 你的见解非常准确:useQuery 本质上是一个QueryObserver在你的组件和 之间创建订阅的函数QueryCache。它的工作原理如下:

// What you write const { data, isLoading } = useQuery({ queryKey: ['user', 1], queryFn: () => fetchUser(1) })

// What actually happens internally const observer = new QueryObserver(queryClient, { queryKey: ['user', 1], queryFn: () => fetchUser(1) })

// Observer creates subscription to QueryCache observer.subscribe(componentCallback) 🧠 更广阔的视野 显示更大的图景

本文将 React Query 从“魔法钩子库”转变为一个复杂的数据编排系统。关键在于,React Query 不仅仅是为了简化 API 调用,更是为了为 React 应用创建一个可预测、高性能且可扩展的数据层。 架构理解(QueryClient → QueryCache → Query → QueryObserver)为您提供了所需的思维模型: 1- 有效调试 React Query 问题 2- 通过理解重新渲染模式来优化性能 3- 设计更好的数据获取策略 4- 避免常见的陷阱,例如不稳定的 QueryClient 实例

💭 外卖 学习如何使用:“使用 React Query hooks 来获取和缓存数据”。 当你理解为什么使用:“QueryClient 协调共享状态,QueryCache 消除重复请求,QueryObserver 支持选择性重新渲染”,你将获得一个强大的数据编排系统,使你的 React 应用程序更高效、更可预测。查看更多www.mxwd.cc