useQueries
的新 APInotifyOnChangeProps
属性不再接受 "tracked"
作为值notifyOnChangePropsExclusion
已被移除cancelRefetch
的一致行为onSuccess
不再从 setQueryData
中调用persistQueryClient
和相应的 persister 插件不再是实验性的,并且已被重命名cancel
方法setLogger
已移除queryClient
、query
和 mutation
中移除未文档化的方法src/react
目录已重命名为 src/reactjs
v4 是一个主要版本,因此有一些重大更改需要注意
您将需要卸载/安装依赖项并更改导入
npm uninstall react-query
npm install @tanstack/react-query
npm install @tanstack/react-query-devtools
npm uninstall react-query
npm install @tanstack/react-query
npm install @tanstack/react-query-devtools
- import { useQuery } from 'react-query' // [!code --]
- import { ReactQueryDevtools } from 'react-query/devtools' // [!code --]
+ import { useQuery } from '@tanstack/react-query' // [!code ++]
+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' // [!code ++]
- import { useQuery } from 'react-query' // [!code --]
- import { ReactQueryDevtools } from 'react-query/devtools' // [!code --]
+ import { useQuery } from '@tanstack/react-query' // [!code ++]
+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' // [!code ++]
为了使导入迁移更容易,v4 附带了一个 codemod。
codemod 是尽力帮助您迁移重大更改的尝试。请彻底审查生成的代码!此外,还有一些边缘情况无法通过代码修改找到,因此请密切关注日志输出。
您可以使用以下命令之一(或两者都用)轻松应用它
如果您想针对 .js 或 .jsx 文件运行它,请使用以下命令
npx jscodeshift ./path/to/src/ \
--extensions=js,jsx \
--transform=./node_modules/@tanstack/react-query/codemods/v4/replace-import-specifier.js
npx jscodeshift ./path/to/src/ \
--extensions=js,jsx \
--transform=./node_modules/@tanstack/react-query/codemods/v4/replace-import-specifier.js
如果您想针对 .ts 或 .tsx 文件运行它,请使用以下命令
npx jscodeshift ./path/to/src/ \
--extensions=ts,tsx \
--parser=tsx \
--transform=./node_modules/@tanstack/react-query/codemods/v4/replace-import-specifier.js
npx jscodeshift ./path/to/src/ \
--extensions=ts,tsx \
--parser=tsx \
--transform=./node_modules/@tanstack/react-query/codemods/v4/replace-import-specifier.js
请注意,在 TypeScript 的情况下,您需要使用 tsx 作为解析器;否则,codemod 将无法正确应用!
注意: 应用 codemod 可能会破坏您的代码格式,因此请不要忘记在应用 codemod 后运行 prettier 和/或 eslint!
注意: codemod 将仅更改导入 - 您仍然必须手动安装单独的 devtools 包。
在 v3 中,Query 和 Mutation Keys 可以是 String 或 Array。在内部,React Query 始终仅使用 Array Keys 工作,并且我们有时会向消费者公开这一点。例如,在 queryFn 中,您将始终获得作为 Array 的 key,以便更轻松地使用 默认 Query 函数。
但是,我们没有将这个概念贯彻到所有 api 中。例如,当在 Query 过滤器 上使用 predicate 函数时,您将获得原始 Query Key。如果您使用混合了 Arrays 和 Strings 的 Query Keys,这将使使用此类函数变得困难。使用全局回调时也是如此。
为了简化所有 api,我们决定将所有 key 都设为仅限 Arrays
;-useQuery('todos', fetchTodos) + // [!code --]
useQuery(['todos'], fetchTodos) // [!code ++]
;-useQuery('todos', fetchTodos) + // [!code --]
useQuery(['todos'], fetchTodos) // [!code ++]
为了使迁移更容易,我们决定交付一个 codemod。
codemod 是尽力帮助您迁移重大更改的尝试。请彻底审查生成的代码!此外,还有一些边缘情况无法通过代码修改找到,因此请密切关注日志输出。
您可以使用以下命令之一(或两者都用)轻松应用它
如果您想针对 .js 或 .jsx 文件运行它,请使用以下命令
npx jscodeshift ./path/to/src/ \
--extensions=js,jsx \
--transform=./node_modules/@tanstack/react-query/codemods/v4/key-transformation.js
npx jscodeshift ./path/to/src/ \
--extensions=js,jsx \
--transform=./node_modules/@tanstack/react-query/codemods/v4/key-transformation.js
如果您想针对 .ts 或 .tsx 文件运行它,请使用以下命令
npx jscodeshift ./path/to/src/ \
--extensions=ts,tsx \
--parser=tsx \
--transform=./node_modules/@tanstack/react-query/codemods/v4/key-transformation.js
npx jscodeshift ./path/to/src/ \
--extensions=ts,tsx \
--parser=tsx \
--transform=./node_modules/@tanstack/react-query/codemods/v4/key-transformation.js
请注意,在 TypeScript 的情况下,您需要使用 tsx 作为解析器;否则,codemod 将无法正确应用!
注意: 应用 codemod 可能会破坏您的代码格式,因此请不要忘记在应用 codemod 后运行 prettier 和/或 eslint!
随着新的 fetchStatus 的引入,以获得更好的离线支持,idle 状态变得无关紧要,因为 fetchStatus: 'idle' 更好地捕获了相同的状态。有关更多信息,请阅读 为什么是两种不同的状态。
这主要会影响 disabled 且没有任何 data 的 queries,因为这些 queries 之前处于 idle 状态
- status: 'idle' // [!code --]
+ status: 'loading' // [!code ++]
+ fetchStatus: 'idle' // [!code ++]
- status: 'idle' // [!code --]
+ status: 'loading' // [!code ++]
+ fetchStatus: 'idle' // [!code ++]
另请参阅 关于依赖 queries 的指南
由于此更改,禁用的 queries(即使是临时禁用的 queries)将以 loading 状态启动。为了使迁移更容易,特别是为了获得一个良好的标志来知道何时显示加载指示器,您可以检查 isInitialLoading 而不是 isLoading
;-isLoading + // [!code --]
isInitialLoading // [!code ++]
;-isLoading + // [!code --]
isInitialLoading // [!code ++]
另请参阅关于 禁用 queries 的指南
useQueries
的新 APIuseQueries
hook 现在接受一个带有 queries
prop 的对象作为其输入。queries
prop 的值是一个 queries 数组(此数组与 v3 中传递给 useQueries
的数组相同)。
;-useQueries([
{ queryKey1, queryFn1, options1 },
{ queryKey2, queryFn2, options2 },
]) + // [!code --]
useQueries({
queries: [
{ queryKey1, queryFn1, options1 },
{ queryKey2, queryFn2, options2 },
],
}) // [!code ++]
;-useQueries([
{ queryKey1, queryFn1, options1 },
{ queryKey2, queryFn2, options2 },
]) + // [!code --]
useQueries({
queries: [
{ queryKey1, queryFn1, options1 },
{ queryKey2, queryFn2, options2 },
],
}) // [!code ++]
为了使通过返回 undefined 来退出更新成为可能,我们不得不使 undefined 成为非法缓存值。这与其他 react-query 的概念一致,例如,从 initialData 函数 返回 undefined 也不会设置数据。
此外,通过在 queryFn 中添加日志记录来生成 Promise<void> 很容易产生错误
useQuery(['key'], () =>
axios.get(url).then((result) => console.log(result.data)),
)
useQuery(['key'], () =>
axios.get(url).then((result) => console.log(result.data)),
)
现在类型级别上不允许这样做;在运行时,undefined 将转换为失败的 Promise,这意味着您将收到一个 error,该 error 也将在开发模式下记录到控制台。
请阅读关于在线/离线支持的 新功能公告,以及关于 网络模式 的专用页面
即使 React Query 是一个异步状态管理器,可以用于任何产生 Promise 的事物,但它最常用于数据获取,并结合数据获取库。这就是为什么,默认情况下,如果没有任何网络连接,queries 和 mutations 将被 paused。如果您想选择加入以前的行为,您可以为 queries 和 mutations 全局设置 networkMode: offlineFirst
new QueryClient({
defaultOptions: {
queries: {
networkMode: 'offlineFirst',
},
mutations: {
networkMode: 'offlineFirst',
},
},
})
new QueryClient({
defaultOptions: {
queries: {
networkMode: 'offlineFirst',
},
mutations: {
networkMode: 'offlineFirst',
},
},
})
notifyOnChangeProps
属性不再接受 "tracked" 作为值notifyOnChangeProps
选项不再接受 "tracked" 值。相反,useQuery
默认跟踪属性。所有使用 notifyOnChangeProps: "tracked"
的 queries 都应通过删除此选项来更新。
如果您想在任何 queries 中绕过此设置以模拟 v3 的默认行为(每当 query 更改时重新渲染),则 notifyOnChangeProps
现在接受 "all" 值以选择退出默认的智能跟踪优化。
notifyOnChangePropsExclusion
已被移除在 v4 中,notifyOnChangeProps
默认为 v3 的 "tracked" 行为,而不是 undefined。既然 "tracked" 是 v4 的默认行为,那么包含此配置选项就没有任何意义了。
cancelRefetch
的一致行为cancelRefetch
选项可以传递给所有命令式获取 query 的函数,即
useQuery
返回的 refetch
useInfiniteQuery
返回的 fetchNextPage
和 fetchPreviousPage
除了 fetchNextPage
和 fetchPreviousPage
之外,此标志默认为 false
,这不一致且可能很麻烦:如果在先前的慢速获取已在进行中,则在 mutation 之后调用 refetchQueries
或 invalidateQueries
可能不会产生最新的结果,因为此重新获取将被跳过。
我们认为,如果 query 被您编写的某些代码主动重新获取,则默认情况下,它应该重新启动获取。
这就是为什么此标志现在对于上面提到的所有方法都默认为 true。这也意味着,如果您连续两次调用 refetchQueries
而不等待它,它现在将取消第一个获取并使用第二个获取重新启动它
queryClient.refetchQueries({ queryKey: ['todos'] })
// this will abort the previous refetch and start a new fetch
queryClient.refetchQueries({ queryKey: ['todos'] })
queryClient.refetchQueries({ queryKey: ['todos'] })
// this will abort the previous refetch and start a new fetch
queryClient.refetchQueries({ queryKey: ['todos'] })
您可以通过显式传递 cancelRefetch:false
来选择退出此行为
queryClient.refetchQueries({ queryKey: ['todos'] })
// this will not abort the previous refetch - it will just be ignored
queryClient.refetchQueries({ queryKey: ['todos'] }, { cancelRefetch: false })
queryClient.refetchQueries({ queryKey: ['todos'] })
// this will not abort the previous refetch - it will just be ignored
queryClient.refetchQueries({ queryKey: ['todos'] }, { cancelRefetch: false })
注意:对于自动触发的获取(例如,因为 query 挂载或因为窗口焦点重新获取)的行为没有变化。
query 过滤器 是一个具有某些条件以匹配 query 的对象。从历史上看,过滤器选项主要是布尔标志的组合。但是,组合这些标志可能会导致不可能的状态。具体来说
active?: boolean
- When set to true it will match active queries.
- When set to false it will match inactive queries.
inactive?: boolean
- When set to true it will match inactive queries.
- When set to false it will match active queries.
active?: boolean
- When set to true it will match active queries.
- When set to false it will match inactive queries.
inactive?: boolean
- When set to true it will match inactive queries.
- When set to false it will match active queries.
当这些标志一起使用时,它们不能很好地工作,因为它们是互斥的。从描述来看,将这两个标志都设置为 false
可能会匹配所有 queries,或者不匹配任何 queries,这没有多大意义。
在 v4 中,这些过滤器已合并为一个过滤器,以更好地显示意图
- active?: boolean // [!code --]
- inactive?: boolean // [!code --]
+ type?: 'active' | 'inactive' | 'all' // [!code ++]
- active?: boolean // [!code --]
- inactive?: boolean // [!code --]
+ type?: 'active' | 'inactive' | 'all' // [!code ++]
过滤器默认为 all
,您可以选择仅匹配 active
或 inactive
queries。
queryClient.invalidateQueries 有两个额外的类似标志
refetchActive: Boolean
- Defaults to true
- When set to false, queries that match the refetch predicate and are actively being rendered
via useQuery and friends will NOT be refetched in the background, and only marked as invalid.
refetchInactive: Boolean
- Defaults to false
- When set to true, queries that match the refetch predicate and are not being rendered
via useQuery and friends will be both marked as invalid and also refetched in the background
refetchActive: Boolean
- Defaults to true
- When set to false, queries that match the refetch predicate and are actively being rendered
via useQuery and friends will NOT be refetched in the background, and only marked as invalid.
refetchInactive: Boolean
- Defaults to false
- When set to true, queries that match the refetch predicate and are not being rendered
via useQuery and friends will be both marked as invalid and also refetched in the background
出于同样的原因,这些标志也已合并
- refetchActive?: boolean // [!code --]
- refetchInactive?: boolean // [!code --]
+ refetchType?: 'active' | 'inactive' | 'all' | 'none' // [!code ++]
- refetchActive?: boolean // [!code --]
- refetchInactive?: boolean // [!code --]
+ refetchType?: 'active' | 'inactive' | 'all' | 'none' // [!code ++]
此标志默认为 active
,因为 refetchActive
默认为 true
。这意味着我们还需要一种方法来告诉 invalidateQueries
完全不重新获取,这就是为什么这里也允许第四个选项 (none
)。
onSuccess
不再从 setQueryData
中调用这让很多人感到困惑,并且如果从 onSuccess
中调用 setQueryData
,也会创建无限循环。当与 staleTime
结合使用时,这也是一个常见的错误来源,因为如果仅从缓存中读取数据,则不会调用 onSuccess
。
与 onError
和 onSettled
类似,onSuccess
回调现在与正在发出的请求相关联。没有请求 -> 没有回调。
如果您想监听 data
字段的更改,您最好使用 useEffect
来执行此操作,其中 data
是依赖项数组的一部分。由于 React Query 通过结构共享确保数据稳定,因此效果不会在每次后台重新获取时执行,而只会当 data 中的某些内容发生更改时执行
const { data } = useQuery({ queryKey, queryFn })
React.useEffect(() => mySideEffectHere(data), [data])
const { data } = useQuery({ queryKey, queryFn })
React.useEffect(() => mySideEffectHere(data), [data])
persistQueryClient
和相应的 persister 插件不再是实验性的,并且已被重命名插件 createWebStoragePersistor
和 createAsyncStoragePersistor
已分别重命名为 createSyncStoragePersister
和 createAsyncStoragePersister
。persistQueryClient
中的接口 Persistor
也已重命名为 Persister
。查看 此 stackexchange 以了解此更改的动机。
由于这些插件不再是实验性的,因此它们的导入路径也已更新
- import { persistQueryClient } from 'react-query/persistQueryClient-experimental' // [!code --]
- import { createWebStoragePersistor } from 'react-query/createWebStoragePersistor-experimental' // [!code --]
- import { createAsyncStoragePersistor } from 'react-query/createAsyncStoragePersistor-experimental' // [!code --]
+ import { persistQueryClient } from '@tanstack/react-query-persist-client' // [!code ++]
+ import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister' // [!code ++]
+ import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' // [!code ++]
- import { persistQueryClient } from 'react-query/persistQueryClient-experimental' // [!code --]
- import { createWebStoragePersistor } from 'react-query/createWebStoragePersistor-experimental' // [!code --]
- import { createAsyncStoragePersistor } from 'react-query/createAsyncStoragePersistor-experimental' // [!code --]
+ import { persistQueryClient } from '@tanstack/react-query-persist-client' // [!code ++]
+ import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister' // [!code ++]
+ import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' // [!code ++]
cancel
方法旧的 cancel
方法 允许您在 promises 上定义一个 cancel
函数,该函数然后被库用于支持 query 取消,已被移除。我们建议使用 更新的 API(在 v3.30.0 中引入),该 API 在内部使用 AbortController
API,并为您提供一个 AbortSignal
实例,供您的 query 函数支持 query 取消。
类型现在需要使用 TypeScript v4.1 或更高版本
从 v4 开始,React Query 针对现代浏览器进行了优化。我们更新了 browserslist 以生成更现代、性能更高且更小的 bundle。您可以在 此处 阅读有关要求的更多信息。
setLogger
已移除可以通过调用 setLogger
全局更改 logger。在 v4 中,该函数被创建 QueryClient
时的可选字段替换。
- import { QueryClient, setLogger } from 'react-query'; // [!code --]
+ import { QueryClient } from '@tanstack/react-query'; // [!code ++]
- setLogger(customLogger) // [!code --]
- const queryClient = new QueryClient(); // [!code --]
+ const queryClient = new QueryClient({ logger: customLogger }) // [!code ++]
- import { QueryClient, setLogger } from 'react-query'; // [!code --]
+ import { QueryClient } from '@tanstack/react-query'; // [!code ++]
- setLogger(customLogger) // [!code --]
- const queryClient = new QueryClient(); // [!code --]
+ const queryClient = new QueryClient({ logger: customLogger }) // [!code ++]
在 v3 中,React Query 会将 query 结果缓存 5 分钟的默认时间,然后手动垃圾回收该数据。此默认值也适用于服务器端 React Query。
这导致了高内存消耗和挂起的进程等待此手动垃圾回收完成。在 v4 中,默认情况下,服务器端 cacheTime
现在设置为 Infinity
,从而有效地禁用手动垃圾回收(NodeJS 进程将在请求完成后清除所有内容)。
此更改仅影响服务器端 React Query 的用户,例如使用 Next.js 的用户。如果您手动设置 cacheTime
,则此更改不会影响您(尽管您可能希望镜像行为)。
从 v4 开始,react-query 将不再在生产模式下将错误(例如,获取失败)记录到控制台,因为这让很多人感到困惑。错误仍会在开发模式下显示。
React Query 现在支持 package.json "exports"
,并且完全兼容 Node 的 CommonJS 和 ESM 的原生解析。我们预计这对大多数用户来说不会是重大更改,但这会将您可以导入到项目中的文件限制为我们官方支持的入口点。
手动订阅 QueryCache
始终为您提供 QueryCacheNotifyEvent
,但这对于 MutationCache
来说并非如此。我们简化了行为,并相应地调整了事件名称。
- type: 'queryAdded' // [!code --]
+ type: 'added' // [!code ++]
- type: 'queryRemoved' // [!code --]
+ type: 'removed' // [!code ++]
- type: 'queryUpdated' // [!code --]
+ type: 'updated' // [!code ++]
- type: 'queryAdded' // [!code --]
+ type: 'added' // [!code ++]
- type: 'queryRemoved' // [!code --]
+ type: 'removed' // [!code ++]
- type: 'queryUpdated' // [!code --]
+ type: 'updated' // [!code ++]
MutationCacheNotifyEvent
使用与 QueryCacheNotifyEvent
相同的类型。
注意:仅当您通过
queryCache.subscribe
或mutationCache.subscribe
手动订阅缓存时,此项才相关
在版本 3.22.0 中,hydration 实用程序已移至 React Query 核心。在 v3 中,您仍然可以使用来自 react-query/hydration
的旧导出,但这些导出已在 v4 中移除。
- import { dehydrate, hydrate, useHydrate, Hydrate } from 'react-query/hydration' // [!code --]
+ import { dehydrate, hydrate, useHydrate, Hydrate } from '@tanstack/react-query' // [!code ++]
- import { dehydrate, hydrate, useHydrate, Hydrate } from 'react-query/hydration' // [!code --]
+ import { dehydrate, hydrate, useHydrate, Hydrate } from '@tanstack/react-query' // [!code ++]
queryClient
、query
和 mutation
中移除未文档化的方法QueryClient
上的方法 cancelMutations
和 executeMutation
未文档化且在内部未使用,因此我们将其移除。由于它只是 mutationCache
上可用方法的包装器,您仍然可以使用 executeMutation
的功能
- executeMutation< // [!code --]
- TData = unknown, // [!code --]
- TError = unknown, // [!code --]
- TVariables = void, // [!code --]
- TContext = unknown // [!code --]
- >( // [!code --]
- options: MutationOptions<TData, TError, TVariables, TContext> // [!code --]
- ): Promise<TData> { // [!code --]
- return this.mutationCache.build(this, options).execute() // [!code --]
- } // [!code --]
- executeMutation< // [!code --]
- TData = unknown, // [!code --]
- TError = unknown, // [!code --]
- TVariables = void, // [!code --]
- TContext = unknown // [!code --]
- >( // [!code --]
- options: MutationOptions<TData, TError, TVariables, TContext> // [!code --]
- ): Promise<TData> { // [!code --]
- return this.mutationCache.build(this, options).execute() // [!code --]
- } // [!code --]
此外,query.setDefaultOptions
已被移除,因为它也未使用。mutation.cancel
已被移除,因为它实际上并没有取消传出的请求。
src/react
目录已重命名为 src/reactjs
以前,React Query 有一个名为 react
的目录,该目录从 react
模块导入。这可能会导致某些 Jest 配置出现问题,从而在运行测试时导致如下错误
TypeError: Cannot read property 'createContext' of undefined
TypeError: Cannot read property 'createContext' of undefined
使用重命名的目录,这不再是一个问题。
如果你在你的项目中直接从 'react-query/react' 导入任何内容 (而不是仅仅 'react-query'),那么你需要更新你的导入
- import { QueryClientProvider } from 'react-query/react'; // [!code --]
+ import { QueryClientProvider } from '@tanstack/react-query/reactjs'; // [!code ++]
- import { QueryClientProvider } from 'react-query/react'; // [!code --]
+ import { QueryClientProvider } from '@tanstack/react-query/reactjs'; // [!code ++]
v4 带来了一系列令人兴奋的新功能
React 18 在今年早些时候发布,v4 现在对其以及它带来的新的并发特性提供了高级支持。
在 v3 中,React Query 总是会触发查询和 mutation,但随后假设如果你想重试,你需要连接到互联网。 这导致了一些令人困惑的情况
在 v4 中,React Query 引入了一个新的 networkMode 来解决所有这些问题。 请阅读关于新的 Network mode 的专门页面以获取更多信息。
React Query 默认使用 "跟踪" 查询属性,这应该会给你带来渲染优化的良好提升。 该功能自 v3.6.0 版本就已存在,现在已成为 v4 的默认行为。
当使用 setQueryData 的函数式更新器形式时,你现在可以通过返回 undefined 来退出更新。 如果 undefined 作为 previousValue 提供给你,这将很有帮助,这意味着当前不存在缓存条目,并且你不想/不能创建一个,就像在切换 todo 的示例中一样。
queryClient.setQueryData(['todo', id], (previousTodo) =>
previousTodo ? { ...previousTodo, done: true } : undefined,
)
queryClient.setQueryData(['todo', id], (previousTodo) =>
previousTodo ? { ...previousTodo, done: true } : undefined,
)
现在 mutations 也可以像 queries 一样自动进行垃圾回收。 mutations 的默认 cacheTime 也设置为 5 分钟。
现在可以指定自定义上下文 (Custom contexts) 以将 hooks 与其匹配的 Provider 配对。 当组件树中可能存在多个 React Query Provider 实例时,这至关重要,你需要确保你的 hook 使用正确的 Provider 实例。
示例
// Our first data package: @my-scope/container-data
const context = React.createContext<QueryClient | undefined>(undefined)
const queryClient = new QueryClient()
export const useUser = () => {
return useQuery(USER_KEY, USER_FETCHER, {
context,
})
}
export const ContainerDataProvider = ({
children,
}: {
children: React.ReactNode
}) => {
return (
<QueryClientProvider client={queryClient} context={context}>
{children}
</QueryClientProvider>
)
}
// Our first data package: @my-scope/container-data
const context = React.createContext<QueryClient | undefined>(undefined)
const queryClient = new QueryClient()
export const useUser = () => {
return useQuery(USER_KEY, USER_FETCHER, {
context,
})
}
export const ContainerDataProvider = ({
children,
}: {
children: React.ReactNode
}) => {
return (
<QueryClientProvider client={queryClient} context={context}>
{children}
</QueryClientProvider>
)
}
// Our second data package: @my-scope/my-component-data
const context = React.createContext<QueryClient | undefined>(undefined)
const queryClient = new QueryClient()
export const useItems = () => {
return useQuery(ITEMS_KEY, ITEMS_FETCHER, {
context,
})
}
export const MyComponentDataProvider = ({
children,
}: {
children: React.ReactNode
}) => {
return (
<QueryClientProvider client={queryClient} context={context}>
{children}
</QueryClientProvider>
)
}
// Our second data package: @my-scope/my-component-data
const context = React.createContext<QueryClient | undefined>(undefined)
const queryClient = new QueryClient()
export const useItems = () => {
return useQuery(ITEMS_KEY, ITEMS_FETCHER, {
context,
})
}
export const MyComponentDataProvider = ({
children,
}: {
children: React.ReactNode
}) => {
return (
<QueryClientProvider client={queryClient} context={context}>
{children}
</QueryClientProvider>
)
}
// Our application
import { ContainerDataProvider, useUser } from "@my-scope/container-data";
import { AppDataProvider } from "@my-scope/app-data";
import { MyComponentDataProvider, useItems } from "@my-scope/my-component-data";
<ContainerDataProvider> // <-- Provides container data (like "user") using its own React Query provider
...
<AppDataProvider> // <-- Provides app data using its own React Query provider (unused in this example)
...
<MyComponentDataProvider> // <-- Provides component data (like "items") using its own React Query provider
<MyComponent />
</MyComponentDataProvider>
...
</AppDataProvider>
...
</ContainerDataProvider>
// Example of hooks provided by the "DataProvider" components above:
const MyComponent = () => {
const user = useUser() // <-- Uses the context specified in ContainerDataProvider.
const items = useItems() // <-- Uses the context specified in MyComponentDataProvider
...
}
// Our application
import { ContainerDataProvider, useUser } from "@my-scope/container-data";
import { AppDataProvider } from "@my-scope/app-data";
import { MyComponentDataProvider, useItems } from "@my-scope/my-component-data";
<ContainerDataProvider> // <-- Provides container data (like "user") using its own React Query provider
...
<AppDataProvider> // <-- Provides app data using its own React Query provider (unused in this example)
...
<MyComponentDataProvider> // <-- Provides component data (like "items") using its own React Query provider
<MyComponent />
</MyComponentDataProvider>
...
</AppDataProvider>
...
</ContainerDataProvider>
// Example of hooks provided by the "DataProvider" components above:
const MyComponent = () => {
const user = useUser() // <-- Uses the context specified in ContainerDataProvider.
const items = useItems() // <-- Uses the context specified in MyComponentDataProvider
...
}