React Query使用
1. React Query 里的核心概念
-
QueryClient:数据缓存的主体,存所有
queryKey → queryState。 不同QueryClient主体之间的数据是不会共通的,除非hydrate到同1个QueryClientProvider节点树里(相同于同1个React Context)。 -
HydrationBoundary:一个 React 组件,作用是接收服务端的“脱水数据” (
dehydratedState),再调用hydrate合并进客户端的QueryClient。 多个HydrationBoundary脱水数据会合并到同1个顶层QueryClient- dehydrate:把
QueryClient当前的缓存序列化成 JSON,丢给服务端 -
hydrate:把 JSON 里的数据写回到
QueryClient实例里
- dehydrate:把
2. 举例
<QueryClientProvider client={queryClient}>
<HydrationBoundary state={dehydratedStateA}>
<ComponentA />
</HydrationBoundary>
<HydrationBoundary state={dehydratedStateB}>
<ComponentB />
</HydrationBoundary>
</QueryClientProvider>
发生了什么?
-
React 渲染
<HydrationBoundary>时,内部会调用hydrate(queryClient, dehydratedState)。 -
hydrate并不会新建QueryClient,而是把数据合并hydrate到当前 Provider 里的同一个QueryClient。 -
所以多个
HydrationBoundary会依次调用hydrate,把它们的脱水数据都写进同一个缓存。 -
最终浏览器端 hydration 时,
queryClient已经有了合并后的完整缓存。
3. SSR
在Nextjs中,当client component在server端进行1次render时,作用方式基本等同于在client端:
- 区别: 在server端只有1次初始render,client端会结果useEffect等多次render
- 相同: 都支持从同1个QueryClientProvider来共享hydrate数据
// page.tsx export async function() { await serverQuery.prefetch([ { queryKey: ['questions', initialFilters, initialPagination], queryFn: () => listQuestions(initialFilters, initialPagination), } ]) const dehydratedState = serverQuery.dehydratedState() return ( <HydrationBoundary state={dehydratedState}> <ClientComp /> </HydrationBoundary> ) } // client-comp.tsx export function() { const queryClient = useQueryClient() /* 虽然是不同queryClient,但是会共享顶层的hyrdation数据。因为Page.tsx会预获取数据,所以这里在server端/client端都是拿到共享数据,不会在初次render发请求 */ const { data, isLoading, error } = useQuery({ queryKey: ['questions', filters, pagination], queryFn: () => listQuestions(filters, pagination), }) // ..... }
浙公网安备 33010602011771号