@tanstack/react-query 5.0.0-alpha.9 → 5.0.0-alpha.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) hide show
  1. package/build/codemods/remove-overloads/remove-overloads.js +59 -0
  2. package/build/codemods/remove-overloads/transformers/filter-aware-usage-transformer.js +153 -0
  3. package/build/codemods/remove-overloads/transformers/query-fn-aware-usage-transformer.js +188 -0
  4. package/build/codemods/remove-overloads/utils/index.js +124 -0
  5. package/build/codemods/remove-overloads/utils/unknown-usage-error.js +27 -0
  6. package/build/codemods/rename-hydrate/rename-hydrate.js +55 -0
  7. package/build/codemods/rename-properties/rename-properties.js +41 -0
  8. package/build/codemods/src/utils/index.js +205 -0
  9. package/build/codemods/src/v4/key-transformation.js +138 -0
  10. package/build/codemods/src/v4/replace-import-specifier.js +25 -0
  11. package/build/codemods/transformers/query-cache-transformer.js +116 -0
  12. package/build/codemods/transformers/query-client-transformer.js +48 -0
  13. package/build/codemods/transformers/use-query-like-transformer.js +32 -0
  14. package/build/codemods/utils/replacers/key-replacer.js +164 -0
  15. package/build/legacy/HydrationBoundary.cjs +60 -0
  16. package/build/legacy/HydrationBoundary.cjs.map +1 -0
  17. package/build/legacy/HydrationBoundary.d.cts +12 -0
  18. package/build/legacy/HydrationBoundary.d.ts +12 -0
  19. package/build/legacy/HydrationBoundary.js +26 -0
  20. package/build/legacy/HydrationBoundary.js.map +1 -0
  21. package/build/legacy/QueryClientProvider.cjs +71 -0
  22. package/build/legacy/QueryClientProvider.cjs.map +1 -0
  23. package/build/legacy/QueryClientProvider.d.cts +12 -0
  24. package/build/legacy/QueryClientProvider.d.ts +12 -0
  25. package/build/legacy/QueryClientProvider.js +35 -0
  26. package/build/legacy/QueryClientProvider.js.map +1 -0
  27. package/build/legacy/QueryErrorResetBoundary.cjs +66 -0
  28. package/build/legacy/QueryErrorResetBoundary.cjs.map +1 -0
  29. package/build/legacy/QueryErrorResetBoundary.d.cts +14 -0
  30. package/build/legacy/QueryErrorResetBoundary.d.ts +14 -0
  31. package/build/legacy/QueryErrorResetBoundary.js +31 -0
  32. package/build/legacy/QueryErrorResetBoundary.js.map +1 -0
  33. package/build/legacy/errorBoundaryUtils.cjs +67 -0
  34. package/build/legacy/errorBoundaryUtils.cjs.map +1 -0
  35. package/build/legacy/errorBoundaryUtils.d.cts +14 -0
  36. package/build/legacy/errorBoundaryUtils.d.ts +14 -0
  37. package/build/legacy/errorBoundaryUtils.js +31 -0
  38. package/build/legacy/errorBoundaryUtils.js.map +1 -0
  39. package/build/legacy/index.cjs +85 -0
  40. package/build/legacy/index.cjs.map +1 -0
  41. package/build/legacy/index.d.cts +17 -0
  42. package/build/legacy/index.d.ts +17 -0
  43. package/build/legacy/index.js +46 -0
  44. package/build/legacy/index.js.map +1 -0
  45. package/build/legacy/infiniteQueryOptions.cjs +33 -0
  46. package/build/legacy/infiniteQueryOptions.cjs.map +1 -0
  47. package/build/legacy/infiniteQueryOptions.d.cts +13 -0
  48. package/build/legacy/infiniteQueryOptions.d.ts +13 -0
  49. package/build/legacy/infiniteQueryOptions.js +8 -0
  50. package/build/legacy/infiniteQueryOptions.js.map +1 -0
  51. package/build/legacy/isRestoring.cjs +47 -0
  52. package/build/legacy/isRestoring.cjs.map +1 -0
  53. package/build/legacy/isRestoring.d.cts +6 -0
  54. package/build/legacy/isRestoring.d.ts +6 -0
  55. package/build/legacy/isRestoring.js +12 -0
  56. package/build/legacy/isRestoring.js.map +1 -0
  57. package/build/legacy/queryOptions.cjs +33 -0
  58. package/build/legacy/queryOptions.cjs.map +1 -0
  59. package/build/legacy/queryOptions.d.cts +13 -0
  60. package/build/legacy/queryOptions.d.ts +13 -0
  61. package/build/legacy/queryOptions.js +8 -0
  62. package/build/legacy/queryOptions.js.map +1 -0
  63. package/build/legacy/suspense.cjs +48 -0
  64. package/build/legacy/suspense.cjs.map +1 -0
  65. package/build/legacy/suspense.d.cts +10 -0
  66. package/build/legacy/suspense.d.ts +10 -0
  67. package/build/legacy/suspense.js +20 -0
  68. package/build/legacy/suspense.js.map +1 -0
  69. package/build/legacy/types.cjs +19 -0
  70. package/build/legacy/types.cjs.map +1 -0
  71. package/build/legacy/types.d.cts +34 -0
  72. package/build/legacy/types.d.ts +34 -0
  73. package/build/legacy/types.js +1 -0
  74. package/build/legacy/types.js.map +1 -0
  75. package/build/legacy/useBaseQuery.cjs +92 -0
  76. package/build/legacy/useBaseQuery.cjs.map +1 -0
  77. package/build/legacy/useBaseQuery.d.cts +92 -0
  78. package/build/legacy/useBaseQuery.d.ts +92 -0
  79. package/build/legacy/useBaseQuery.js +62 -0
  80. package/build/legacy/useBaseQuery.js.map +1 -0
  81. package/build/legacy/useInfiniteQuery.cjs +41 -0
  82. package/build/legacy/useInfiniteQuery.cjs.map +1 -0
  83. package/build/legacy/useInfiniteQuery.d.cts +8 -0
  84. package/build/legacy/useInfiniteQuery.d.ts +8 -0
  85. package/build/legacy/useInfiniteQuery.js +17 -0
  86. package/build/legacy/useInfiniteQuery.js.map +1 -0
  87. package/build/legacy/useIsFetching.cjs +56 -0
  88. package/build/legacy/useIsFetching.cjs.map +1 -0
  89. package/build/legacy/useIsFetching.d.cts +5 -0
  90. package/build/legacy/useIsFetching.d.ts +5 -0
  91. package/build/legacy/useIsFetching.js +22 -0
  92. package/build/legacy/useIsFetching.js.map +1 -0
  93. package/build/legacy/useMutation.cjs +77 -0
  94. package/build/legacy/useMutation.cjs.map +1 -0
  95. package/build/legacy/useMutation.d.cts +6 -0
  96. package/build/legacy/useMutation.d.ts +6 -0
  97. package/build/legacy/useMutation.js +43 -0
  98. package/build/legacy/useMutation.js.map +1 -0
  99. package/build/legacy/useMutationState.cjs +88 -0
  100. package/build/legacy/useMutationState.cjs.map +1 -0
  101. package/build/legacy/useMutationState.d.cts +10 -0
  102. package/build/legacy/useMutationState.d.ts +10 -0
  103. package/build/legacy/useMutationState.js +53 -0
  104. package/build/legacy/useMutationState.js.map +1 -0
  105. package/build/legacy/useQueries.cjs +128 -0
  106. package/build/legacy/useQueries.cjs.map +1 -0
  107. package/build/legacy/useQueries.d.cts +53 -0
  108. package/build/{lib → legacy}/useQueries.d.ts +14 -11
  109. package/build/legacy/useQueries.js +103 -0
  110. package/build/legacy/useQueries.js.map +1 -0
  111. package/build/legacy/useQuery.cjs +36 -0
  112. package/build/legacy/useQuery.cjs.map +1 -0
  113. package/build/legacy/useQuery.d.cts +8 -0
  114. package/build/legacy/useQuery.d.ts +8 -0
  115. package/build/legacy/useQuery.js +12 -0
  116. package/build/legacy/useQuery.js.map +1 -0
  117. package/build/legacy/useSuspenseInfiniteQuery.cjs +46 -0
  118. package/build/legacy/useSuspenseInfiniteQuery.cjs.map +1 -0
  119. package/build/legacy/useSuspenseInfiniteQuery.d.cts +6 -0
  120. package/build/legacy/useSuspenseInfiniteQuery.d.ts +6 -0
  121. package/build/legacy/useSuspenseInfiniteQuery.js +22 -0
  122. package/build/legacy/useSuspenseInfiniteQuery.js.map +1 -0
  123. package/build/legacy/useSuspenseQuery.cjs +45 -0
  124. package/build/legacy/useSuspenseQuery.cjs.map +1 -0
  125. package/build/legacy/useSuspenseQuery.d.cts +6 -0
  126. package/build/legacy/useSuspenseQuery.d.ts +6 -0
  127. package/build/legacy/useSuspenseQuery.js +21 -0
  128. package/build/legacy/useSuspenseQuery.js.map +1 -0
  129. package/build/legacy/utils.cjs +36 -0
  130. package/build/legacy/utils.cjs.map +1 -0
  131. package/build/legacy/utils.d.cts +3 -0
  132. package/build/legacy/utils.d.ts +3 -0
  133. package/build/legacy/utils.js +11 -0
  134. package/build/legacy/utils.js.map +1 -0
  135. package/build/modern/HydrationBoundary.cjs +60 -0
  136. package/build/modern/HydrationBoundary.cjs.map +1 -0
  137. package/build/modern/HydrationBoundary.d.cts +12 -0
  138. package/build/modern/HydrationBoundary.d.ts +12 -0
  139. package/build/modern/HydrationBoundary.js +26 -0
  140. package/build/modern/HydrationBoundary.js.map +1 -0
  141. package/build/modern/QueryClientProvider.cjs +71 -0
  142. package/build/modern/QueryClientProvider.cjs.map +1 -0
  143. package/build/modern/QueryClientProvider.d.cts +12 -0
  144. package/build/modern/QueryClientProvider.d.ts +12 -0
  145. package/build/modern/QueryClientProvider.js +35 -0
  146. package/build/modern/QueryClientProvider.js.map +1 -0
  147. package/build/modern/QueryErrorResetBoundary.cjs +66 -0
  148. package/build/modern/QueryErrorResetBoundary.cjs.map +1 -0
  149. package/build/modern/QueryErrorResetBoundary.d.cts +14 -0
  150. package/build/modern/QueryErrorResetBoundary.d.ts +14 -0
  151. package/build/modern/QueryErrorResetBoundary.js +31 -0
  152. package/build/modern/QueryErrorResetBoundary.js.map +1 -0
  153. package/build/modern/errorBoundaryUtils.cjs +67 -0
  154. package/build/modern/errorBoundaryUtils.cjs.map +1 -0
  155. package/build/modern/errorBoundaryUtils.d.cts +14 -0
  156. package/build/modern/errorBoundaryUtils.d.ts +14 -0
  157. package/build/modern/errorBoundaryUtils.js +31 -0
  158. package/build/modern/errorBoundaryUtils.js.map +1 -0
  159. package/build/modern/index.cjs +85 -0
  160. package/build/modern/index.cjs.map +1 -0
  161. package/build/modern/index.d.cts +17 -0
  162. package/build/modern/index.d.ts +17 -0
  163. package/build/modern/index.js +46 -0
  164. package/build/modern/index.js.map +1 -0
  165. package/build/modern/infiniteQueryOptions.cjs +33 -0
  166. package/build/modern/infiniteQueryOptions.cjs.map +1 -0
  167. package/build/modern/infiniteQueryOptions.d.cts +13 -0
  168. package/build/modern/infiniteQueryOptions.d.ts +13 -0
  169. package/build/modern/infiniteQueryOptions.js +8 -0
  170. package/build/modern/infiniteQueryOptions.js.map +1 -0
  171. package/build/modern/isRestoring.cjs +47 -0
  172. package/build/modern/isRestoring.cjs.map +1 -0
  173. package/build/modern/isRestoring.d.cts +6 -0
  174. package/build/modern/isRestoring.d.ts +6 -0
  175. package/build/modern/isRestoring.js +12 -0
  176. package/build/modern/isRestoring.js.map +1 -0
  177. package/build/modern/queryOptions.cjs +33 -0
  178. package/build/modern/queryOptions.cjs.map +1 -0
  179. package/build/modern/queryOptions.d.cts +13 -0
  180. package/build/modern/queryOptions.d.ts +13 -0
  181. package/build/modern/queryOptions.js +8 -0
  182. package/build/modern/queryOptions.js.map +1 -0
  183. package/build/modern/suspense.cjs +48 -0
  184. package/build/modern/suspense.cjs.map +1 -0
  185. package/build/modern/suspense.d.cts +10 -0
  186. package/build/modern/suspense.d.ts +10 -0
  187. package/build/modern/suspense.js +20 -0
  188. package/build/modern/suspense.js.map +1 -0
  189. package/build/modern/types.cjs +19 -0
  190. package/build/modern/types.cjs.map +1 -0
  191. package/build/modern/types.d.cts +34 -0
  192. package/build/modern/types.d.ts +34 -0
  193. package/build/modern/types.js +1 -0
  194. package/build/modern/types.js.map +1 -0
  195. package/build/modern/useBaseQuery.cjs +92 -0
  196. package/build/modern/useBaseQuery.cjs.map +1 -0
  197. package/build/modern/useBaseQuery.d.cts +92 -0
  198. package/build/modern/useBaseQuery.d.ts +92 -0
  199. package/build/modern/useBaseQuery.js +62 -0
  200. package/build/modern/useBaseQuery.js.map +1 -0
  201. package/build/modern/useInfiniteQuery.cjs +41 -0
  202. package/build/modern/useInfiniteQuery.cjs.map +1 -0
  203. package/build/modern/useInfiniteQuery.d.cts +8 -0
  204. package/build/modern/useInfiniteQuery.d.ts +8 -0
  205. package/build/modern/useInfiniteQuery.js +17 -0
  206. package/build/modern/useInfiniteQuery.js.map +1 -0
  207. package/build/modern/useIsFetching.cjs +56 -0
  208. package/build/modern/useIsFetching.cjs.map +1 -0
  209. package/build/modern/useIsFetching.d.cts +5 -0
  210. package/build/modern/useIsFetching.d.ts +5 -0
  211. package/build/modern/useIsFetching.js +22 -0
  212. package/build/modern/useIsFetching.js.map +1 -0
  213. package/build/modern/useMutation.cjs +77 -0
  214. package/build/modern/useMutation.cjs.map +1 -0
  215. package/build/modern/useMutation.d.cts +6 -0
  216. package/build/modern/useMutation.d.ts +6 -0
  217. package/build/modern/useMutation.js +43 -0
  218. package/build/modern/useMutation.js.map +1 -0
  219. package/build/modern/useMutationState.cjs +88 -0
  220. package/build/modern/useMutationState.cjs.map +1 -0
  221. package/build/modern/useMutationState.d.cts +10 -0
  222. package/build/modern/useMutationState.d.ts +10 -0
  223. package/build/modern/useMutationState.js +53 -0
  224. package/build/modern/useMutationState.js.map +1 -0
  225. package/build/modern/useQueries.cjs +125 -0
  226. package/build/modern/useQueries.cjs.map +1 -0
  227. package/build/modern/useQueries.d.cts +53 -0
  228. package/build/modern/useQueries.d.ts +53 -0
  229. package/build/modern/useQueries.js +100 -0
  230. package/build/modern/useQueries.js.map +1 -0
  231. package/build/modern/useQuery.cjs +36 -0
  232. package/build/modern/useQuery.cjs.map +1 -0
  233. package/build/modern/useQuery.d.cts +8 -0
  234. package/build/modern/useQuery.d.ts +8 -0
  235. package/build/modern/useQuery.js +12 -0
  236. package/build/modern/useQuery.js.map +1 -0
  237. package/build/modern/useSuspenseInfiniteQuery.cjs +46 -0
  238. package/build/modern/useSuspenseInfiniteQuery.cjs.map +1 -0
  239. package/build/modern/useSuspenseInfiniteQuery.d.cts +6 -0
  240. package/build/modern/useSuspenseInfiniteQuery.d.ts +6 -0
  241. package/build/modern/useSuspenseInfiniteQuery.js +22 -0
  242. package/build/modern/useSuspenseInfiniteQuery.js.map +1 -0
  243. package/build/modern/useSuspenseQuery.cjs +45 -0
  244. package/build/modern/useSuspenseQuery.cjs.map +1 -0
  245. package/build/modern/useSuspenseQuery.d.cts +6 -0
  246. package/build/modern/useSuspenseQuery.d.ts +6 -0
  247. package/build/modern/useSuspenseQuery.js +21 -0
  248. package/build/modern/useSuspenseQuery.js.map +1 -0
  249. package/build/modern/utils.cjs +36 -0
  250. package/build/modern/utils.cjs.map +1 -0
  251. package/build/modern/utils.d.cts +3 -0
  252. package/build/modern/utils.d.ts +3 -0
  253. package/build/modern/utils.js +11 -0
  254. package/build/modern/utils.js.map +1 -0
  255. package/package.json +29 -17
  256. package/src/HydrationBoundary.tsx +1 -1
  257. package/src/__tests__/HydrationBoundary.test.tsx +5 -5
  258. package/src/__tests__/QueryClientProvider.test.tsx +2 -2
  259. package/src/__tests__/QueryResetErrorBoundary.test.tsx +753 -621
  260. package/src/__tests__/ssr-hydration.test.tsx +4 -4
  261. package/src/__tests__/ssr.test.tsx +2 -2
  262. package/src/__tests__/suspense.test.tsx +8 -90
  263. package/src/__tests__/useInfiniteQuery.test.tsx +36 -74
  264. package/src/__tests__/useInfiniteQuery.type.test.tsx +2 -29
  265. package/src/__tests__/useIsFetching.test.tsx +1 -1
  266. package/src/__tests__/useMutation.test.tsx +22 -23
  267. package/src/__tests__/useMutationState.test.tsx +23 -0
  268. package/src/__tests__/useQueries.test.tsx +214 -91
  269. package/src/__tests__/useQuery.test.tsx +431 -453
  270. package/src/__tests__/useQuery.types.test.tsx +22 -1
  271. package/src/__tests__/utils.tsx +11 -5
  272. package/src/errorBoundaryUtils.ts +7 -7
  273. package/src/index.ts +4 -0
  274. package/src/infiniteQueryOptions.ts +93 -0
  275. package/src/queryOptions.ts +42 -0
  276. package/src/suspense.ts +9 -15
  277. package/src/types.ts +50 -8
  278. package/src/useBaseQuery.ts +14 -26
  279. package/src/useInfiniteQuery.ts +50 -7
  280. package/src/useIsFetching.ts +1 -1
  281. package/src/useMutation.ts +4 -4
  282. package/src/useMutationState.ts +8 -8
  283. package/src/useQueries.ts +53 -36
  284. package/src/useQuery.ts +6 -21
  285. package/src/useSuspenseInfiniteQuery.ts +47 -0
  286. package/src/useSuspenseQuery.ts +26 -0
  287. package/build/lib/HydrationBoundary.d.ts +0 -9
  288. package/build/lib/HydrationBoundary.esm.js +0 -29
  289. package/build/lib/HydrationBoundary.esm.js.map +0 -1
  290. package/build/lib/HydrationBoundary.js +0 -50
  291. package/build/lib/HydrationBoundary.js.map +0 -1
  292. package/build/lib/HydrationBoundary.mjs +0 -29
  293. package/build/lib/HydrationBoundary.mjs.map +0 -1
  294. package/build/lib/QueryClientProvider.d.ts +0 -9
  295. package/build/lib/QueryClientProvider.esm.js +0 -31
  296. package/build/lib/QueryClientProvider.esm.js.map +0 -1
  297. package/build/lib/QueryClientProvider.js +0 -54
  298. package/build/lib/QueryClientProvider.js.map +0 -1
  299. package/build/lib/QueryClientProvider.mjs +0 -31
  300. package/build/lib/QueryClientProvider.mjs.map +0 -1
  301. package/build/lib/QueryErrorResetBoundary.d.ts +0 -11
  302. package/build/lib/QueryErrorResetBoundary.esm.js +0 -38
  303. package/build/lib/QueryErrorResetBoundary.esm.js.map +0 -1
  304. package/build/lib/QueryErrorResetBoundary.js +0 -60
  305. package/build/lib/QueryErrorResetBoundary.js.map +0 -1
  306. package/build/lib/QueryErrorResetBoundary.mjs +0 -38
  307. package/build/lib/QueryErrorResetBoundary.mjs.map +0 -1
  308. package/build/lib/__tests__/HydrationBoundary.test.d.ts +0 -1
  309. package/build/lib/__tests__/QueryClientProvider.test.d.ts +0 -1
  310. package/build/lib/__tests__/QueryResetErrorBoundary.test.d.ts +0 -6
  311. package/build/lib/__tests__/ssr-hydration.test.d.ts +0 -1
  312. package/build/lib/__tests__/ssr.test.d.ts +0 -1
  313. package/build/lib/__tests__/suspense.test.d.ts +0 -1
  314. package/build/lib/__tests__/useInfiniteQuery.test.d.ts +0 -1
  315. package/build/lib/__tests__/useInfiniteQuery.type.test.d.ts +0 -1
  316. package/build/lib/__tests__/useIsFetching.test.d.ts +0 -1
  317. package/build/lib/__tests__/useMutation.test.d.ts +0 -1
  318. package/build/lib/__tests__/useMutationState.test.d.ts +0 -1
  319. package/build/lib/__tests__/useQueries.test.d.ts +0 -1
  320. package/build/lib/__tests__/useQuery.test.d.ts +0 -1
  321. package/build/lib/__tests__/useQuery.types.test.d.ts +0 -1
  322. package/build/lib/__tests__/utils.d.ts +0 -28
  323. package/build/lib/errorBoundaryUtils.d.ts +0 -10
  324. package/build/lib/errorBoundaryUtils.esm.js +0 -28
  325. package/build/lib/errorBoundaryUtils.esm.js.map +0 -1
  326. package/build/lib/errorBoundaryUtils.js +0 -51
  327. package/build/lib/errorBoundaryUtils.js.map +0 -1
  328. package/build/lib/errorBoundaryUtils.mjs +0 -28
  329. package/build/lib/errorBoundaryUtils.mjs.map +0 -1
  330. package/build/lib/index.d.ts +0 -16
  331. package/build/lib/index.esm.js +0 -12
  332. package/build/lib/index.esm.js.map +0 -1
  333. package/build/lib/index.js +0 -38
  334. package/build/lib/index.js.map +0 -1
  335. package/build/lib/index.mjs +0 -12
  336. package/build/lib/index.mjs.map +0 -1
  337. package/build/lib/isRestoring.d.ts +0 -3
  338. package/build/lib/isRestoring.esm.js +0 -9
  339. package/build/lib/isRestoring.esm.js.map +0 -1
  340. package/build/lib/isRestoring.js +0 -31
  341. package/build/lib/isRestoring.js.map +0 -1
  342. package/build/lib/isRestoring.mjs +0 -9
  343. package/build/lib/isRestoring.mjs.map +0 -1
  344. package/build/lib/suspense.d.ts +0 -9
  345. package/build/lib/suspense.esm.js +0 -24
  346. package/build/lib/suspense.esm.js.map +0 -1
  347. package/build/lib/suspense.js +0 -29
  348. package/build/lib/suspense.js.map +0 -1
  349. package/build/lib/suspense.mjs +0 -24
  350. package/build/lib/suspense.mjs.map +0 -1
  351. package/build/lib/types.d.ts +0 -26
  352. package/build/lib/useBaseQuery.d.ts +0 -3
  353. package/build/lib/useBaseQuery.esm.js +0 -63
  354. package/build/lib/useBaseQuery.esm.js.map +0 -1
  355. package/build/lib/useBaseQuery.js +0 -84
  356. package/build/lib/useBaseQuery.js.map +0 -1
  357. package/build/lib/useBaseQuery.mjs +0 -63
  358. package/build/lib/useBaseQuery.mjs.map +0 -1
  359. package/build/lib/useInfiniteQuery.d.ts +0 -3
  360. package/build/lib/useInfiniteQuery.esm.js +0 -13
  361. package/build/lib/useInfiniteQuery.esm.js.map +0 -1
  362. package/build/lib/useInfiniteQuery.js +0 -15
  363. package/build/lib/useInfiniteQuery.js.map +0 -1
  364. package/build/lib/useInfiniteQuery.mjs +0 -13
  365. package/build/lib/useInfiniteQuery.mjs.map +0 -1
  366. package/build/lib/useIsFetching.d.ts +0 -2
  367. package/build/lib/useIsFetching.esm.js +0 -13
  368. package/build/lib/useIsFetching.esm.js.map +0 -1
  369. package/build/lib/useIsFetching.js +0 -34
  370. package/build/lib/useIsFetching.js.map +0 -1
  371. package/build/lib/useIsFetching.mjs +0 -13
  372. package/build/lib/useIsFetching.mjs.map +0 -1
  373. package/build/lib/useMutation.d.ts +0 -3
  374. package/build/lib/useMutation.esm.js +0 -33
  375. package/build/lib/useMutation.esm.js.map +0 -1
  376. package/build/lib/useMutation.js +0 -54
  377. package/build/lib/useMutation.js.map +0 -1
  378. package/build/lib/useMutation.mjs +0 -33
  379. package/build/lib/useMutation.mjs.map +0 -1
  380. package/build/lib/useMutationState.d.ts +0 -8
  381. package/build/lib/useMutationState.esm.js +0 -38
  382. package/build/lib/useMutationState.esm.js.map +0 -1
  383. package/build/lib/useMutationState.js +0 -60
  384. package/build/lib/useMutationState.js.map +0 -1
  385. package/build/lib/useMutationState.mjs +0 -38
  386. package/build/lib/useMutationState.mjs.map +0 -1
  387. package/build/lib/useQueries.esm.js +0 -73
  388. package/build/lib/useQueries.esm.js.map +0 -1
  389. package/build/lib/useQueries.js +0 -94
  390. package/build/lib/useQueries.js.map +0 -1
  391. package/build/lib/useQueries.mjs +0 -70
  392. package/build/lib/useQueries.mjs.map +0 -1
  393. package/build/lib/useQuery.d.ts +0 -11
  394. package/build/lib/useQuery.esm.js +0 -12
  395. package/build/lib/useQuery.esm.js.map +0 -1
  396. package/build/lib/useQuery.js +0 -14
  397. package/build/lib/useQuery.js.map +0 -1
  398. package/build/lib/useQuery.mjs +0 -12
  399. package/build/lib/useQuery.mjs.map +0 -1
  400. package/build/lib/utils.d.ts +0 -1
  401. package/build/lib/utils.esm.js +0 -10
  402. package/build/lib/utils.esm.js.map +0 -1
  403. package/build/lib/utils.js +0 -12
  404. package/build/lib/utils.js.map +0 -1
  405. package/build/lib/utils.mjs +0 -10
  406. package/build/lib/utils.mjs.map +0 -1
  407. package/build/umd/index.development.js +0 -3040
  408. package/build/umd/index.development.js.map +0 -1
  409. package/build/umd/index.production.js +0 -2
  410. package/build/umd/index.production.js.map +0 -1
  411. /package/src/{isRestoring.tsx → isRestoring.ts} +0 -0
@@ -1,11 +1,14 @@
1
1
  import { act, fireEvent, render, waitFor } from '@testing-library/react'
2
2
  import '@testing-library/jest-dom'
3
3
  import * as React from 'react'
4
+ import { ErrorBoundary } from 'react-error-boundary'
5
+ import { vi } from 'vitest'
6
+ import { QueryCache, keepPreviousData, useQuery } from '..'
4
7
  import {
5
8
  Blink,
6
9
  createQueryClient,
7
10
  expectType,
8
- mockNavigatorOnLine,
11
+ mockOnlineManagerIsOnline,
9
12
  mockVisibilityState,
10
13
  queryKey,
11
14
  renderWithClient,
@@ -15,13 +18,9 @@ import {
15
18
  import type {
16
19
  DefinedUseQueryResult,
17
20
  QueryFunction,
18
- QueryFunctionContext,
19
21
  UseQueryOptions,
20
22
  UseQueryResult,
21
23
  } from '..'
22
- import { QueryCache, useQuery, keepPreviousData } from '..'
23
- import { ErrorBoundary } from 'react-error-boundary'
24
- import { vi } from 'vitest'
25
24
  import type { Mock } from 'vitest'
26
25
 
27
26
  describe('useQuery', () => {
@@ -64,23 +63,17 @@ describe('useQuery', () => {
64
63
  useQuery({
65
64
  queryKey: [key],
66
65
  queryFn: async () => true,
67
- onSuccess: (data) => expectType<boolean>(data),
68
- onSettled: (data) => expectType<boolean | undefined>(data),
69
66
  })
70
67
 
71
68
  // it should be possible to specify a union type as result type
72
69
  const unionTypeSync = useQuery({
73
70
  queryKey: key,
74
71
  queryFn: () => (Math.random() > 0.5 ? 'a' : 'b'),
75
-
76
- onSuccess: (data) => expectType<'a' | 'b'>(data),
77
72
  })
78
73
  expectType<'a' | 'b' | undefined>(unionTypeSync.data)
79
74
  const unionTypeAsync = useQuery<'a' | 'b'>({
80
75
  queryKey: key,
81
76
  queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),
82
-
83
- onSuccess: (data) => expectType<'a' | 'b'>(data),
84
77
  })
85
78
  expectType<'a' | 'b' | undefined>(unionTypeAsync.data)
86
79
 
@@ -450,255 +443,6 @@ describe('useQuery', () => {
450
443
  })
451
444
  })
452
445
 
453
- it('should call onSuccess after a query has been fetched', async () => {
454
- const key = queryKey()
455
- const states: UseQueryResult<string>[] = []
456
- const onSuccess = vi.fn()
457
-
458
- function Page() {
459
- const state = useQuery({
460
- queryKey: key,
461
- queryFn: async () => {
462
- await sleep(10)
463
- return 'data'
464
- },
465
- onSuccess,
466
- })
467
- states.push(state)
468
- return <div>data: {state.data}</div>
469
- }
470
-
471
- const rendered = renderWithClient(queryClient, <Page />)
472
-
473
- await rendered.findByText('data: data')
474
- expect(states.length).toBe(2)
475
- expect(onSuccess).toHaveBeenCalledTimes(1)
476
- expect(onSuccess).toHaveBeenCalledWith('data')
477
- })
478
-
479
- it('should call onSuccess after a query has been refetched', async () => {
480
- const key = queryKey()
481
- const states: UseQueryResult<string>[] = []
482
- const onSuccess = vi.fn()
483
- let count = 0
484
-
485
- function Page() {
486
- const state = useQuery({
487
- queryKey: key,
488
- queryFn: async () => {
489
- count++
490
- await sleep(10)
491
- return 'data' + count
492
- },
493
- onSuccess,
494
- })
495
-
496
- states.push(state)
497
-
498
- return (
499
- <div>
500
- <div>data: {state.data}</div>
501
- <button onClick={() => state.refetch()}>refetch</button>
502
- </div>
503
- )
504
- }
505
-
506
- const rendered = renderWithClient(queryClient, <Page />)
507
-
508
- await rendered.findByText('data: data1')
509
- fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))
510
- await rendered.findByText('data: data2')
511
-
512
- expect(states.length).toBe(3) //pending, success, success after refetch
513
- expect(count).toBe(2)
514
- expect(onSuccess).toHaveBeenCalledTimes(2)
515
- })
516
-
517
- it('should call onSuccess after a disabled query has been fetched', async () => {
518
- const key = queryKey()
519
- const states: UseQueryResult<string>[] = []
520
- const onSuccess = vi.fn()
521
-
522
- function Page() {
523
- const state = useQuery({
524
- queryKey: key,
525
- queryFn: () => 'data',
526
- enabled: false,
527
- onSuccess,
528
- })
529
-
530
- states.push(state)
531
-
532
- return (
533
- <div>
534
- <div>isSuccess: {state.isSuccess ? 'true' : 'false'}</div>
535
- <button onClick={() => state.refetch()}>refetch</button>
536
- </div>
537
- )
538
- }
539
-
540
- const rendered = renderWithClient(queryClient, <Page />)
541
-
542
- await waitFor(() => {
543
- rendered.getByText('isSuccess: false')
544
- })
545
-
546
- fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
547
-
548
- await waitFor(() => {
549
- rendered.getByText('isSuccess: true')
550
- })
551
-
552
- expect(onSuccess).toHaveBeenCalledTimes(1)
553
- expect(onSuccess).toHaveBeenCalledWith('data')
554
- })
555
-
556
- it('should not call onSuccess if a component has unmounted', async () => {
557
- const key = queryKey()
558
- const states: UseQueryResult<string>[] = []
559
- const onSuccess = vi.fn()
560
-
561
- function Page() {
562
- const [show, setShow] = React.useState(true)
563
-
564
- React.useEffect(() => {
565
- setShow(false)
566
- }, [setShow])
567
-
568
- return show ? <Component /> : null
569
- }
570
-
571
- function Component() {
572
- const state = useQuery({
573
- queryKey: key,
574
- queryFn: async () => {
575
- await sleep(10)
576
- return 'data'
577
- },
578
- onSuccess,
579
- })
580
- states.push(state)
581
- return null
582
- }
583
-
584
- renderWithClient(queryClient, <Page />)
585
-
586
- await sleep(50)
587
- expect(states.length).toBe(1)
588
- expect(onSuccess).toHaveBeenCalledTimes(0)
589
- })
590
-
591
- it('should call onError after a query has been fetched with an error', async () => {
592
- const key = queryKey()
593
- const states: UseQueryResult<unknown>[] = []
594
- const onError = vi.fn()
595
-
596
- function Page() {
597
- const state = useQuery<unknown>({
598
- queryKey: key,
599
- queryFn: () => Promise.reject(new Error('error')),
600
- retry: false,
601
- onError,
602
- })
603
- states.push(state)
604
- return null
605
- }
606
-
607
- renderWithClient(queryClient, <Page />)
608
-
609
- await sleep(10)
610
- expect(states.length).toBe(2)
611
- expect(onError).toHaveBeenCalledTimes(1)
612
- expect(onError).toHaveBeenCalledWith(new Error('error'))
613
- })
614
-
615
- it('should not call onError when receiving a CancelledError', async () => {
616
- const key = queryKey()
617
- const onError = vi.fn()
618
-
619
- function Page() {
620
- const { status, fetchStatus } = useQuery({
621
- queryKey: key,
622
- queryFn: async () => {
623
- await sleep(10)
624
- return 23
625
- },
626
-
627
- onError,
628
- })
629
- return (
630
- <span>
631
- status: {status}, fetchStatus: {fetchStatus}
632
- </span>
633
- )
634
- }
635
-
636
- const rendered = renderWithClient(queryClient, <Page />)
637
-
638
- rendered.getByText('status: pending, fetchStatus: fetching')
639
-
640
- await queryClient.cancelQueries({ queryKey: key })
641
- // query cancellation will reset the query to it's initial state
642
- await waitFor(() =>
643
- rendered.getByText('status: pending, fetchStatus: idle'),
644
- )
645
- expect(onError).not.toHaveBeenCalled()
646
- })
647
-
648
- it('should call onSettled after a query has been fetched', async () => {
649
- const key = queryKey()
650
- const states: UseQueryResult<string>[] = []
651
- const onSettled = vi.fn()
652
-
653
- function Page() {
654
- const state = useQuery({
655
- queryKey: key,
656
- queryFn: () => 'data',
657
- onSettled,
658
- })
659
- states.push(state)
660
-
661
- return <div>data: {state.data}</div>
662
- }
663
-
664
- const rendered = renderWithClient(queryClient, <Page />)
665
-
666
- await waitFor(() => {
667
- rendered.getByText('data: data')
668
- })
669
-
670
- expect(states.length).toBe(2)
671
- expect(onSettled).toHaveBeenCalledTimes(1)
672
- expect(onSettled).toHaveBeenCalledWith('data', null)
673
- })
674
-
675
- it('should call onSettled after a query has been fetched with an error', async () => {
676
- const key = queryKey()
677
- const onSettled = vi.fn()
678
- const error = new Error('error')
679
-
680
- function Page() {
681
- const state = useQuery({
682
- queryKey: key,
683
- queryFn: async () => {
684
- await sleep(10)
685
- return Promise.reject(error)
686
- },
687
- retry: false,
688
- onSettled,
689
- })
690
- return <div>status: {state.status}</div>
691
- }
692
-
693
- const rendered = renderWithClient(queryClient, <Page />)
694
-
695
- await waitFor(() => {
696
- rendered.getByText('status: error')
697
- })
698
- expect(onSettled).toHaveBeenCalledTimes(1)
699
- expect(onSettled).toHaveBeenCalledWith(undefined, error)
700
- })
701
-
702
446
  it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => {
703
447
  const key = queryKey()
704
448
  let fetchCount = 0
@@ -948,17 +692,15 @@ describe('useQuery', () => {
948
692
  // required to make sure no additional renders are happening after data is successfully fetched for the second time
949
693
  await sleep(100)
950
694
 
951
- expect(states.length).toBe(5)
695
+ expect(states.length).toBe(4)
952
696
  // First load
953
697
  expect(states[0]).toMatchObject({ isPending: true, isSuccess: false })
954
698
  // First success
955
699
  expect(states[1]).toMatchObject({ isPending: false, isSuccess: true })
956
700
  // Remove
957
701
  expect(states[2]).toMatchObject({ isPending: true, isSuccess: false })
958
- // Hook state update
959
- expect(states[3]).toMatchObject({ isPending: true, isSuccess: false })
960
702
  // Second success
961
- expect(states[4]).toMatchObject({ isPending: false, isSuccess: true })
703
+ expect(states[3]).toMatchObject({ isPending: false, isSuccess: true })
962
704
  })
963
705
 
964
706
  it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => {
@@ -1664,7 +1406,194 @@ describe('useQuery', () => {
1664
1406
  })
1665
1407
  })
1666
1408
 
1667
- it('should keep the previous data when placeholderData is set', async () => {
1409
+ it('should keep the previous data when placeholderData is set', async () => {
1410
+ const key = queryKey()
1411
+ const states: UseQueryResult<number>[] = []
1412
+
1413
+ function Page() {
1414
+ const [count, setCount] = React.useState(0)
1415
+
1416
+ const state = useQuery({
1417
+ queryKey: [key, count],
1418
+ queryFn: async () => {
1419
+ await sleep(10)
1420
+ return count
1421
+ },
1422
+ placeholderData: keepPreviousData,
1423
+ })
1424
+
1425
+ states.push(state)
1426
+
1427
+ return (
1428
+ <div>
1429
+ <div>data: {state.data}</div>
1430
+ <button onClick={() => setCount(1)}>setCount</button>
1431
+ </div>
1432
+ )
1433
+ }
1434
+
1435
+ const rendered = renderWithClient(queryClient, <Page />)
1436
+
1437
+ await waitFor(() => rendered.getByText('data: 0'))
1438
+
1439
+ fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
1440
+
1441
+ await waitFor(() => rendered.getByText('data: 1'))
1442
+
1443
+ // Initial
1444
+ expect(states[0]).toMatchObject({
1445
+ data: undefined,
1446
+ isFetching: true,
1447
+ isSuccess: false,
1448
+ isPlaceholderData: false,
1449
+ })
1450
+ // Fetched
1451
+ expect(states[1]).toMatchObject({
1452
+ data: 0,
1453
+ isFetching: false,
1454
+ isSuccess: true,
1455
+ isPlaceholderData: false,
1456
+ })
1457
+ // Set state
1458
+ expect(states[2]).toMatchObject({
1459
+ data: 0,
1460
+ isFetching: true,
1461
+ isSuccess: true,
1462
+ isPlaceholderData: true,
1463
+ })
1464
+ // New data
1465
+ expect(states[3]).toMatchObject({
1466
+ data: 1,
1467
+ isFetching: false,
1468
+ isSuccess: true,
1469
+ isPlaceholderData: false,
1470
+ })
1471
+ })
1472
+
1473
+ it('should keep the previous data when placeholderData is set and select fn transform is used', async () => {
1474
+ const key = queryKey()
1475
+ const states: UseQueryResult<number>[] = []
1476
+
1477
+ function Page() {
1478
+ const [count, setCount] = React.useState(0)
1479
+
1480
+ const state = useQuery({
1481
+ queryKey: [key, count],
1482
+ queryFn: async () => {
1483
+ await sleep(10)
1484
+ return {
1485
+ count,
1486
+ }
1487
+ },
1488
+ select(data) {
1489
+ return data.count
1490
+ },
1491
+ placeholderData: keepPreviousData,
1492
+ })
1493
+
1494
+ states.push(state)
1495
+
1496
+ return (
1497
+ <div>
1498
+ <div>data: {state.data}</div>
1499
+ <button onClick={() => setCount(1)}>setCount</button>
1500
+ </div>
1501
+ )
1502
+ }
1503
+
1504
+ const rendered = renderWithClient(queryClient, <Page />)
1505
+
1506
+ await waitFor(() => rendered.getByText('data: 0'))
1507
+
1508
+ fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
1509
+
1510
+ await waitFor(() => rendered.getByText('data: 1'))
1511
+
1512
+ // Initial
1513
+ expect(states[0]).toMatchObject({
1514
+ data: undefined,
1515
+ isFetching: true,
1516
+ isSuccess: false,
1517
+ isPlaceholderData: false,
1518
+ })
1519
+ // Fetched
1520
+ expect(states[1]).toMatchObject({
1521
+ data: 0,
1522
+ isFetching: false,
1523
+ isSuccess: true,
1524
+ isPlaceholderData: false,
1525
+ })
1526
+ // Set state
1527
+ expect(states[2]).toMatchObject({
1528
+ data: 0,
1529
+ isFetching: true,
1530
+ isSuccess: true,
1531
+ isPlaceholderData: true,
1532
+ })
1533
+ // New data
1534
+ expect(states[3]).toMatchObject({
1535
+ data: 1,
1536
+ isFetching: false,
1537
+ isSuccess: true,
1538
+ isPlaceholderData: false,
1539
+ })
1540
+ })
1541
+
1542
+ it('should keep the previous queryKey (from prevQuery) between multiple pending queries when placeholderData is set and select fn transform is used', async () => {
1543
+ const keys: Array<readonly unknown[] | null> = []
1544
+ const key = queryKey()
1545
+ const states: UseQueryResult<number>[] = []
1546
+
1547
+ function Page() {
1548
+ const [count, setCount] = React.useState(0)
1549
+
1550
+ const state = useQuery({
1551
+ queryKey: [key, count],
1552
+ queryFn: async () => {
1553
+ await sleep(10)
1554
+ return {
1555
+ count,
1556
+ }
1557
+ },
1558
+ select(data) {
1559
+ return data.count
1560
+ },
1561
+ placeholderData: (prevData, prevQuery) => {
1562
+ if (prevQuery) {
1563
+ keys.push(prevQuery.queryKey)
1564
+ }
1565
+ return prevData
1566
+ },
1567
+ })
1568
+
1569
+ states.push(state)
1570
+
1571
+ return (
1572
+ <div>
1573
+ <div>data: {state.data}</div>
1574
+ <button onClick={() => setCount((prev) => prev + 1)}>setCount</button>
1575
+ </div>
1576
+ )
1577
+ }
1578
+
1579
+ const rendered = renderWithClient(queryClient, <Page />)
1580
+
1581
+ await waitFor(() => rendered.getByText('data: 0'))
1582
+
1583
+ fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
1584
+ fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
1585
+ fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
1586
+
1587
+ await waitFor(() => rendered.getByText('data: 3'))
1588
+
1589
+ const allPreviousKeysAreTheFirstQueryKey = keys.every(
1590
+ (k) => JSON.stringify(k) === JSON.stringify([key, 0]),
1591
+ )
1592
+
1593
+ expect(allPreviousKeysAreTheFirstQueryKey).toBe(true)
1594
+ })
1595
+
1596
+ it('should show placeholderData between multiple pending queries when select fn transform is used', async () => {
1668
1597
  const key = queryKey()
1669
1598
  const states: UseQueryResult<number>[] = []
1670
1599
 
@@ -1675,7 +1604,12 @@ describe('useQuery', () => {
1675
1604
  queryKey: [key, count],
1676
1605
  queryFn: async () => {
1677
1606
  await sleep(10)
1678
- return count
1607
+ return {
1608
+ count,
1609
+ }
1610
+ },
1611
+ select(data) {
1612
+ return data.count
1679
1613
  },
1680
1614
  placeholderData: keepPreviousData,
1681
1615
  })
@@ -1685,7 +1619,7 @@ describe('useQuery', () => {
1685
1619
  return (
1686
1620
  <div>
1687
1621
  <div>data: {state.data}</div>
1688
- <button onClick={() => setCount(1)}>setCount</button>
1622
+ <button onClick={() => setCount((prev) => prev + 1)}>setCount</button>
1689
1623
  </div>
1690
1624
  )
1691
1625
  }
@@ -1694,10 +1628,11 @@ describe('useQuery', () => {
1694
1628
 
1695
1629
  await waitFor(() => rendered.getByText('data: 0'))
1696
1630
 
1631
+ fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
1632
+ fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
1697
1633
  fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
1698
1634
 
1699
- await waitFor(() => rendered.getByText('data: 1'))
1700
-
1635
+ await waitFor(() => rendered.getByText('data: 3'))
1701
1636
  // Initial
1702
1637
  expect(states[0]).toMatchObject({
1703
1638
  data: undefined,
@@ -1712,16 +1647,30 @@ describe('useQuery', () => {
1712
1647
  isSuccess: true,
1713
1648
  isPlaceholderData: false,
1714
1649
  })
1715
- // Set state
1650
+ // Set state -> count = 1
1716
1651
  expect(states[2]).toMatchObject({
1717
1652
  data: 0,
1718
1653
  isFetching: true,
1719
1654
  isSuccess: true,
1720
1655
  isPlaceholderData: true,
1721
1656
  })
1722
- // New data
1657
+ // Set state -> count = 2
1723
1658
  expect(states[3]).toMatchObject({
1724
- data: 1,
1659
+ data: 0,
1660
+ isFetching: true,
1661
+ isSuccess: true,
1662
+ isPlaceholderData: true,
1663
+ })
1664
+ // Set state -> count = 3
1665
+ expect(states[4]).toMatchObject({
1666
+ data: 0,
1667
+ isFetching: true,
1668
+ isSuccess: true,
1669
+ isPlaceholderData: true,
1670
+ })
1671
+ // New data
1672
+ expect(states[5]).toMatchObject({
1673
+ data: 3,
1725
1674
  isFetching: false,
1726
1675
  isSuccess: true,
1727
1676
  isPlaceholderData: false,
@@ -1764,7 +1713,7 @@ describe('useQuery', () => {
1764
1713
  act(() => rendered.rerender(<Page count={2} />))
1765
1714
  await waitFor(() => rendered.getByText('error: Error test'))
1766
1715
 
1767
- await waitFor(() => expect(states.length).toBe(8))
1716
+ await waitFor(() => expect(states.length).toBe(6))
1768
1717
  // Initial
1769
1718
  expect(states[0]).toMatchObject({
1770
1719
  data: undefined,
@@ -1789,16 +1738,8 @@ describe('useQuery', () => {
1789
1738
  error: null,
1790
1739
  isPlaceholderData: true,
1791
1740
  })
1792
- // Hook state update
1793
- expect(states[3]).toMatchObject({
1794
- data: 0,
1795
- isFetching: true,
1796
- status: 'success',
1797
- error: null,
1798
- isPlaceholderData: true,
1799
- })
1800
1741
  // New data
1801
- expect(states[4]).toMatchObject({
1742
+ expect(states[3]).toMatchObject({
1802
1743
  data: 1,
1803
1744
  isFetching: false,
1804
1745
  status: 'success',
@@ -1806,15 +1747,7 @@ describe('useQuery', () => {
1806
1747
  isPlaceholderData: false,
1807
1748
  })
1808
1749
  // rerender Page 2
1809
- expect(states[5]).toMatchObject({
1810
- data: 1,
1811
- isFetching: true,
1812
- status: 'success',
1813
- error: null,
1814
- isPlaceholderData: true,
1815
- })
1816
- // Hook state update again
1817
- expect(states[6]).toMatchObject({
1750
+ expect(states[4]).toMatchObject({
1818
1751
  data: 1,
1819
1752
  isFetching: true,
1820
1753
  status: 'success',
@@ -1822,13 +1755,13 @@ describe('useQuery', () => {
1822
1755
  isPlaceholderData: true,
1823
1756
  })
1824
1757
  // Error
1825
- expect(states[7]).toMatchObject({
1758
+ expect(states[5]).toMatchObject({
1826
1759
  data: undefined,
1827
1760
  isFetching: false,
1828
1761
  status: 'error',
1829
1762
  isPlaceholderData: false,
1830
1763
  })
1831
- expect(states[7]?.error).toHaveProperty('message', 'Error test')
1764
+ expect(states[5]!.error).toHaveProperty('message', 'Error test')
1832
1765
  })
1833
1766
 
1834
1767
  it('should not show initial data from next query if placeholderData is set', async () => {
@@ -1873,7 +1806,7 @@ describe('useQuery', () => {
1873
1806
  rendered.getByText('data: 1, count: 1, isFetching: false'),
1874
1807
  )
1875
1808
 
1876
- expect(states.length).toBe(5)
1809
+ expect(states.length).toBe(4)
1877
1810
 
1878
1811
  // Initial
1879
1812
  expect(states[0]).toMatchObject({
@@ -1896,15 +1829,8 @@ describe('useQuery', () => {
1896
1829
  isSuccess: true,
1897
1830
  isPlaceholderData: false,
1898
1831
  })
1899
- // Hook state update
1900
- expect(states[3]).toMatchObject({
1901
- data: 99,
1902
- isFetching: true,
1903
- isSuccess: true,
1904
- isPlaceholderData: false,
1905
- })
1906
1832
  // New data
1907
- expect(states[4]).toMatchObject({
1833
+ expect(states[3]).toMatchObject({
1908
1834
  data: 1,
1909
1835
  isFetching: false,
1910
1836
  isSuccess: true,
@@ -2434,53 +2360,6 @@ describe('useQuery', () => {
2434
2360
  expect(renders).toBe(2)
2435
2361
  })
2436
2362
 
2437
- it('should batch re-renders including hook callbacks', async () => {
2438
- const key = queryKey()
2439
-
2440
- let renders = 0
2441
- let callbackCount = 0
2442
-
2443
- const queryFn = async () => {
2444
- await sleep(10)
2445
- return 'data'
2446
- }
2447
-
2448
- function Page() {
2449
- const [count, setCount] = React.useState(0)
2450
- useQuery({
2451
- queryKey: key,
2452
- queryFn,
2453
- onSuccess: () => {
2454
- setCount((x) => x + 1)
2455
- },
2456
- })
2457
- useQuery({
2458
- queryKey: key,
2459
- queryFn,
2460
- onSuccess: () => {
2461
- setCount((x) => x + 1)
2462
- },
2463
- })
2464
-
2465
- React.useEffect(() => {
2466
- renders++
2467
- callbackCount = count
2468
- })
2469
-
2470
- return <div>count: {count}</div>
2471
- }
2472
-
2473
- const rendered = renderWithClient(queryClient, <Page />)
2474
-
2475
- await waitFor(() => rendered.getByText('count: 2'))
2476
-
2477
- // Should be 3 instead of 5
2478
- expect(renders).toBe(3)
2479
-
2480
- // Both callbacks should have been executed
2481
- expect(callbackCount).toBe(2)
2482
- })
2483
-
2484
2363
  it('should render latest data even if react has discarded certain renders', async () => {
2485
2364
  const key = queryKey()
2486
2365
 
@@ -2557,33 +2436,6 @@ describe('useQuery', () => {
2557
2436
  rendered.getByText('status: pending')
2558
2437
  })
2559
2438
 
2560
- // See https://github.com/tannerlinsley/react-query/issues/147
2561
- it('should not pass stringified variables to query function', async () => {
2562
- const key = queryKey()
2563
- const variables = { number: 5, boolean: false, object: {}, array: [] }
2564
- type CustomQueryKey = [typeof key, typeof variables]
2565
- const states: UseQueryResult<CustomQueryKey>[] = []
2566
-
2567
- const queryFn = async (ctx: QueryFunctionContext<CustomQueryKey>) => {
2568
- await sleep(10)
2569
- return ctx.queryKey
2570
- }
2571
-
2572
- function Page() {
2573
- const state = useQuery({ queryKey: [key, variables], queryFn })
2574
- states.push(state)
2575
- return <div>{state.status}</div>
2576
- }
2577
-
2578
- const rendered = renderWithClient(queryClient, <Page />)
2579
-
2580
- await waitFor(() => {
2581
- rendered.getByText('success')
2582
- })
2583
-
2584
- expect(states[1]?.data).toEqual([key, variables])
2585
- })
2586
-
2587
2439
  it('should not refetch query on focus when `enabled` is set to `false`', async () => {
2588
2440
  const key = queryKey()
2589
2441
  const queryFn = vi.fn<unknown[], string>().mockReturnValue('data')
@@ -2723,24 +2575,24 @@ describe('useQuery', () => {
2723
2575
  refetchOnWindowFocus: 'always',
2724
2576
  })
2725
2577
  states.push(state)
2726
- return null
2578
+ return (
2579
+ <div>
2580
+ <div>
2581
+ data: {state.data}, isFetching: {String(state.isFetching)}
2582
+ </div>
2583
+ </div>
2584
+ )
2727
2585
  }
2728
2586
 
2729
- renderWithClient(queryClient, <Page />)
2587
+ const rendered = renderWithClient(queryClient, <Page />)
2730
2588
 
2731
- await sleep(20)
2589
+ await waitFor(() => rendered.getByText('data: 0, isFetching: false'))
2732
2590
 
2733
2591
  act(() => {
2734
2592
  window.dispatchEvent(new Event('visibilitychange'))
2735
2593
  })
2736
2594
 
2737
- await sleep(20)
2738
-
2739
- await waitFor(() => expect(states.length).toBe(4))
2740
- expect(states[0]).toMatchObject({ data: undefined, isFetching: true })
2741
- expect(states[1]).toMatchObject({ data: 0, isFetching: false })
2742
- expect(states[2]).toMatchObject({ data: 0, isFetching: true })
2743
- expect(states[3]).toMatchObject({ data: 1, isFetching: false })
2595
+ await waitFor(() => rendered.getByText('data: 1, isFetching: false'))
2744
2596
  })
2745
2597
 
2746
2598
  it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => {
@@ -2896,7 +2748,7 @@ describe('useQuery', () => {
2896
2748
  await waitFor(() => rendered.getByText('Error test jaylen'))
2897
2749
  })
2898
2750
 
2899
- it('should throw error if queryFn throws and throwErrors is in use', async () => {
2751
+ it('should throw error if queryFn throws and throwOnError is in use', async () => {
2900
2752
  const consoleMock = vi
2901
2753
  .spyOn(console, 'error')
2902
2754
  .mockImplementation(() => undefined)
@@ -2907,7 +2759,7 @@ describe('useQuery', () => {
2907
2759
  queryKey: key,
2908
2760
  queryFn: () => Promise.reject(new Error('Error test jaylen')),
2909
2761
  retry: false,
2910
- throwErrors: true,
2762
+ throwOnError: true,
2911
2763
  })
2912
2764
 
2913
2765
  return (
@@ -2929,7 +2781,7 @@ describe('useQuery', () => {
2929
2781
  consoleMock.mockRestore()
2930
2782
  })
2931
2783
 
2932
- it('should update with data if we observe no properties and throwErrors', async () => {
2784
+ it('should update with data if we observe no properties and throwOnError', async () => {
2933
2785
  const key = queryKey()
2934
2786
 
2935
2787
  let result: UseQueryResult<string> | undefined
@@ -2938,7 +2790,7 @@ describe('useQuery', () => {
2938
2790
  const query = useQuery({
2939
2791
  queryKey: key,
2940
2792
  queryFn: () => Promise.resolve('data'),
2941
- throwErrors: true,
2793
+ throwOnError: true,
2942
2794
  })
2943
2795
 
2944
2796
  React.useEffect(() => {
@@ -2966,7 +2818,7 @@ describe('useQuery', () => {
2966
2818
  queryFn: () => Promise.reject(new Error('Local Error')),
2967
2819
 
2968
2820
  retry: false,
2969
- throwErrors: (err) => err.message !== 'Local Error',
2821
+ throwOnError: (err) => err.message !== 'Local Error',
2970
2822
  })
2971
2823
 
2972
2824
  return (
@@ -3001,7 +2853,7 @@ describe('useQuery', () => {
3001
2853
  queryFn: () => Promise.reject(new Error('Remote Error')),
3002
2854
 
3003
2855
  retry: false,
3004
- throwErrors: (err) => err.message !== 'Local Error',
2856
+ throwOnError: (err) => err.message !== 'Local Error',
3005
2857
  })
3006
2858
 
3007
2859
  return (
@@ -3758,6 +3610,7 @@ describe('useQuery', () => {
3758
3610
  })
3759
3611
  act(() => setPrefetched(true))
3760
3612
  }
3613
+
3761
3614
  prefetch()
3762
3615
  }, [])
3763
3616
 
@@ -5200,7 +5053,7 @@ describe('useQuery', () => {
5200
5053
 
5201
5054
  describe('networkMode online', () => {
5202
5055
  it('online queries should not start fetching if you are offline', async () => {
5203
- const onlineMock = mockNavigatorOnLine(false)
5056
+ const onlineMock = mockOnlineManagerIsOnline(false)
5204
5057
 
5205
5058
  const key = queryKey()
5206
5059
  const states: Array<any> = []
@@ -5229,10 +5082,11 @@ describe('useQuery', () => {
5229
5082
  }
5230
5083
 
5231
5084
  const rendered = renderWithClient(queryClient, <Page />)
5085
+ window.dispatchEvent(new Event('offline'))
5232
5086
 
5233
5087
  await waitFor(() => rendered.getByText('status: pending, isPaused: true'))
5234
5088
 
5235
- onlineMock.mockReturnValue(true)
5089
+ onlineMock.mockRestore()
5236
5090
  window.dispatchEvent(new Event('online'))
5237
5091
 
5238
5092
  await waitFor(() =>
@@ -5243,8 +5097,6 @@ describe('useQuery', () => {
5243
5097
  })
5244
5098
 
5245
5099
  expect(states).toEqual(['paused', 'fetching', 'idle'])
5246
-
5247
- onlineMock.mockRestore()
5248
5100
  })
5249
5101
 
5250
5102
  it('online queries should not refetch if you are offline', async () => {
@@ -5282,7 +5134,9 @@ describe('useQuery', () => {
5282
5134
 
5283
5135
  await waitFor(() => rendered.getByText('data: data1'))
5284
5136
 
5285
- const onlineMock = mockNavigatorOnLine(false)
5137
+ const onlineMock = mockOnlineManagerIsOnline(false)
5138
+ window.dispatchEvent(new Event('offline'))
5139
+
5286
5140
  fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))
5287
5141
 
5288
5142
  await waitFor(() =>
@@ -5292,7 +5146,7 @@ describe('useQuery', () => {
5292
5146
  )
5293
5147
  await waitFor(() => rendered.getByText('failureReason: null'))
5294
5148
 
5295
- onlineMock.mockReturnValue(true)
5149
+ onlineMock.mockRestore()
5296
5150
  window.dispatchEvent(new Event('online'))
5297
5151
 
5298
5152
  await waitFor(() =>
@@ -5311,8 +5165,6 @@ describe('useQuery', () => {
5311
5165
  await waitFor(() => {
5312
5166
  expect(rendered.getByText('data: data2')).toBeInTheDocument()
5313
5167
  })
5314
-
5315
- onlineMock.mockRestore()
5316
5168
  })
5317
5169
 
5318
5170
  it('online queries should not refetch if you are offline and refocus', async () => {
@@ -5348,7 +5200,7 @@ describe('useQuery', () => {
5348
5200
 
5349
5201
  await waitFor(() => rendered.getByText('data: data1'))
5350
5202
 
5351
- const onlineMock = mockNavigatorOnLine(false)
5203
+ const onlineMock = mockOnlineManagerIsOnline(false)
5352
5204
  fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))
5353
5205
 
5354
5206
  await waitFor(() =>
@@ -5394,7 +5246,7 @@ describe('useQuery', () => {
5394
5246
  )
5395
5247
  }
5396
5248
 
5397
- const onlineMock = mockNavigatorOnLine(false)
5249
+ const onlineMock = mockOnlineManagerIsOnline(false)
5398
5250
 
5399
5251
  const rendered = renderWithClient(queryClient, <Page />)
5400
5252
 
@@ -5445,7 +5297,7 @@ describe('useQuery', () => {
5445
5297
  )
5446
5298
  }
5447
5299
 
5448
- const onlineMock = mockNavigatorOnLine(false)
5300
+ const onlineMock = mockOnlineManagerIsOnline(false)
5449
5301
 
5450
5302
  const rendered = renderWithClient(queryClient, <Page />)
5451
5303
 
@@ -5499,9 +5351,10 @@ describe('useQuery', () => {
5499
5351
  )
5500
5352
  }
5501
5353
 
5502
- const onlineMock = mockNavigatorOnLine(false)
5354
+ const onlineMock = mockOnlineManagerIsOnline(false)
5503
5355
 
5504
5356
  const rendered = renderWithClient(queryClient, <Page />)
5357
+ window.dispatchEvent(new Event('offline'))
5505
5358
 
5506
5359
  await waitFor(() =>
5507
5360
  rendered.getByText('status: success, fetchStatus: paused'),
@@ -5524,7 +5377,7 @@ describe('useQuery', () => {
5524
5377
  window.dispatchEvent(new Event('visibilitychange'))
5525
5378
  })
5526
5379
 
5527
- onlineMock.mockReturnValue(true)
5380
+ onlineMock.mockRestore()
5528
5381
  act(() => {
5529
5382
  window.dispatchEvent(new Event('online'))
5530
5383
  })
@@ -5537,7 +5390,6 @@ describe('useQuery', () => {
5537
5390
  })
5538
5391
 
5539
5392
  expect(count).toBe(1)
5540
- onlineMock.mockRestore()
5541
5393
  })
5542
5394
 
5543
5395
  it('online queries should pause retries if you are offline', async () => {
@@ -5570,13 +5422,11 @@ describe('useQuery', () => {
5570
5422
  const rendered = renderWithClient(queryClient, <Page />)
5571
5423
 
5572
5424
  await waitFor(() =>
5573
- rendered.getByText(
5574
- 'status: pending, fetchStatus: fetching, failureCount: 1',
5575
- ),
5425
+ rendered.getByText(/status: pending, fetchStatus: fetching/i),
5576
5426
  )
5577
- await waitFor(() => rendered.getByText('failureReason: failed1'))
5578
5427
 
5579
- const onlineMock = mockNavigatorOnLine(false)
5428
+ const onlineMock = mockOnlineManagerIsOnline(false)
5429
+ window.dispatchEvent(new Event('offline'))
5580
5430
 
5581
5431
  await sleep(20)
5582
5432
 
@@ -5637,17 +5487,19 @@ describe('useQuery', () => {
5637
5487
  )
5638
5488
  }
5639
5489
 
5640
- const onlineMock = mockNavigatorOnLine(false)
5490
+ const onlineMock = mockOnlineManagerIsOnline(false)
5641
5491
 
5642
5492
  const rendered = renderWithClient(queryClient, <Page />)
5643
5493
 
5494
+ window.dispatchEvent(new Event('offline'))
5495
+
5644
5496
  await waitFor(() =>
5645
5497
  rendered.getByText('status: pending, fetchStatus: paused'),
5646
5498
  )
5647
5499
 
5648
5500
  fireEvent.click(rendered.getByRole('button', { name: /hide/i }))
5649
5501
 
5650
- onlineMock.mockReturnValue(true)
5502
+ onlineMock.mockRestore()
5651
5503
  window.dispatchEvent(new Event('online'))
5652
5504
 
5653
5505
  await waitFor(() => {
@@ -5660,8 +5512,6 @@ describe('useQuery', () => {
5660
5512
  // give it a bit more time to make sure queryFn is not called again
5661
5513
  await sleep(15)
5662
5514
  expect(count).toBe(1)
5663
-
5664
- onlineMock.mockRestore()
5665
5515
  })
5666
5516
 
5667
5517
  it('online queries should not fetch if paused and we go online when cancelled and no refetchOnReconnect', async () => {
@@ -5694,7 +5544,7 @@ describe('useQuery', () => {
5694
5544
  )
5695
5545
  }
5696
5546
 
5697
- const onlineMock = mockNavigatorOnLine(false)
5547
+ const onlineMock = mockOnlineManagerIsOnline(false)
5698
5548
 
5699
5549
  const rendered = renderWithClient(queryClient, <Page />)
5700
5550
 
@@ -5770,7 +5620,7 @@ describe('useQuery', () => {
5770
5620
  rendered.getByText('status: success, fetchStatus: idle'),
5771
5621
  )
5772
5622
 
5773
- const onlineMock = mockNavigatorOnLine(false)
5623
+ const onlineMock = mockOnlineManagerIsOnline(false)
5774
5624
 
5775
5625
  fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))
5776
5626
 
@@ -5800,7 +5650,7 @@ describe('useQuery', () => {
5800
5650
 
5801
5651
  describe('networkMode always', () => {
5802
5652
  it('always queries should start fetching even if you are offline', async () => {
5803
- const onlineMock = mockNavigatorOnLine(false)
5653
+ const onlineMock = mockOnlineManagerIsOnline(false)
5804
5654
 
5805
5655
  const key = queryKey()
5806
5656
  let count = 0
@@ -5840,7 +5690,7 @@ describe('useQuery', () => {
5840
5690
  })
5841
5691
 
5842
5692
  it('always queries should not pause retries', async () => {
5843
- const onlineMock = mockNavigatorOnLine(false)
5693
+ const onlineMock = mockOnlineManagerIsOnline(false)
5844
5694
 
5845
5695
  const key = queryKey()
5846
5696
  let count = 0
@@ -5886,7 +5736,7 @@ describe('useQuery', () => {
5886
5736
 
5887
5737
  describe('networkMode offlineFirst', () => {
5888
5738
  it('offlineFirst queries should start fetching if you are offline, but pause retries', async () => {
5889
- const onlineMock = mockNavigatorOnLine(false)
5739
+ const onlineMock = mockOnlineManagerIsOnline(false)
5890
5740
 
5891
5741
  const key = queryKey()
5892
5742
  let count = 0
@@ -5917,6 +5767,8 @@ describe('useQuery', () => {
5917
5767
 
5918
5768
  const rendered = renderWithClient(queryClient, <Page />)
5919
5769
 
5770
+ window.dispatchEvent(new Event('offline'))
5771
+
5920
5772
  await waitFor(() =>
5921
5773
  rendered.getByText(
5922
5774
  'status: pending, fetchStatus: paused, failureCount: 1',
@@ -5926,7 +5778,7 @@ describe('useQuery', () => {
5926
5778
 
5927
5779
  expect(count).toBe(1)
5928
5780
 
5929
- onlineMock.mockReturnValue(true)
5781
+ onlineMock.mockRestore()
5930
5782
  window.dispatchEvent(new Event('online'))
5931
5783
 
5932
5784
  await waitFor(() =>
@@ -5935,8 +5787,6 @@ describe('useQuery', () => {
5935
5787
  await waitFor(() => rendered.getByText('failureReason: failed3'))
5936
5788
 
5937
5789
  expect(count).toBe(3)
5938
-
5939
- onlineMock.mockRestore()
5940
5790
  })
5941
5791
  })
5942
5792
 
@@ -5973,36 +5823,6 @@ describe('useQuery', () => {
5973
5823
  })
5974
5824
  })
5975
5825
 
5976
- it('setQueryData - should not call onSuccess callback of active observers', async () => {
5977
- const key = queryKey()
5978
- const onSuccess = vi.fn()
5979
-
5980
- function Page() {
5981
- const state = useQuery({
5982
- queryKey: key,
5983
- queryFn: () => 'data',
5984
- onSuccess,
5985
- })
5986
- return (
5987
- <div>
5988
- <div>data: {state.data}</div>
5989
- <button onClick={() => queryClient.setQueryData(key, 'newData')}>
5990
- setQueryData
5991
- </button>
5992
- </div>
5993
- )
5994
- }
5995
-
5996
- const rendered = renderWithClient(queryClient, <Page />)
5997
-
5998
- await waitFor(() => rendered.getByText('data: data'))
5999
- fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i }))
6000
- await waitFor(() => rendered.getByText('data: newData'))
6001
-
6002
- expect(onSuccess).toHaveBeenCalledTimes(1)
6003
- expect(onSuccess).toHaveBeenCalledWith('data')
6004
- })
6005
-
6006
5826
  it('setQueryData - should respect updatedAt', async () => {
6007
5827
  const key = queryKey()
6008
5828
 
@@ -6054,6 +5874,7 @@ describe('useQuery', () => {
6054
5874
  </div>
6055
5875
  )
6056
5876
  }
5877
+
6057
5878
  const rendered = renderWithClient(queryClient, <Page />)
6058
5879
  const fetchBtn = rendered.getByRole('button', { name: 'refetch' })
6059
5880
  await waitFor(() => rendered.getByText('data: 1'))
@@ -6085,4 +5906,161 @@ describe('useQuery', () => {
6085
5906
 
6086
5907
  await waitFor(() => rendered.getByText('data: custom client'))
6087
5908
  })
5909
+
5910
+ it('should be notified of updates between create and subscribe', async () => {
5911
+ const key = queryKey()
5912
+
5913
+ function Page() {
5914
+ const mounted = React.useRef<boolean>(false)
5915
+ const { data, status } = useQuery({
5916
+ enabled: false,
5917
+ queryKey: key,
5918
+ queryFn: async () => {
5919
+ await sleep(10)
5920
+ return 5
5921
+ },
5922
+ })
5923
+
5924
+ // this simulates a synchronous update between the time the query is created
5925
+ // and the time it is subscribed to that could be missed otherwise
5926
+ if (!mounted.current) {
5927
+ mounted.current = true
5928
+ queryClient.setQueryData(key, 1)
5929
+ }
5930
+
5931
+ return (
5932
+ <div>
5933
+ <span>status: {status}</span>
5934
+ <span>data: {data}</span>
5935
+ </div>
5936
+ )
5937
+ }
5938
+
5939
+ const rendered = renderWithClient(queryClient, <Page />)
5940
+ await waitFor(() => rendered.getByText('status: success'))
5941
+ await waitFor(() => rendered.getByText('data: 1'))
5942
+ })
5943
+ it('should reuse same data object reference when queryKey changes back to some cached data', async () => {
5944
+ const key = queryKey()
5945
+ const spy = vi.fn()
5946
+
5947
+ async function fetchNumber(id: number) {
5948
+ await sleep(5)
5949
+ return { numbers: { current: { id } } }
5950
+ }
5951
+ function Test() {
5952
+ const [id, setId] = React.useState(1)
5953
+
5954
+ const { data } = useQuery({
5955
+ select: selector,
5956
+ queryKey: [key, 'user', id],
5957
+ queryFn: () => fetchNumber(id),
5958
+ })
5959
+
5960
+ React.useEffect(() => {
5961
+ spy(data)
5962
+ }, [data])
5963
+
5964
+ return (
5965
+ <div>
5966
+ <button name="1" onClick={() => setId(1)}>
5967
+ 1
5968
+ </button>
5969
+ <button name="2" onClick={() => setId(2)}>
5970
+ 2
5971
+ </button>
5972
+ <span>Rendered Id: {data?.id}</span>
5973
+ </div>
5974
+ )
5975
+ }
5976
+
5977
+ function selector(data: any) {
5978
+ return data.numbers.current
5979
+ }
5980
+
5981
+ const rendered = renderWithClient(queryClient, <Test />)
5982
+ expect(spy).toHaveBeenCalledTimes(1)
5983
+
5984
+ spy.mockClear()
5985
+ await waitFor(() => rendered.getByText('Rendered Id: 1'))
5986
+ expect(spy).toHaveBeenCalledTimes(1)
5987
+
5988
+ spy.mockClear()
5989
+ fireEvent.click(rendered.getByRole('button', { name: /2/ }))
5990
+ await waitFor(() => rendered.getByText('Rendered Id: 2'))
5991
+ expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed
5992
+
5993
+ spy.mockClear()
5994
+ fireEvent.click(rendered.getByRole('button', { name: /1/ }))
5995
+ await waitFor(() => rendered.getByText('Rendered Id: 1'))
5996
+ expect(spy).toHaveBeenCalledTimes(1)
5997
+
5998
+ spy.mockClear()
5999
+ fireEvent.click(rendered.getByRole('button', { name: /2/ }))
6000
+ await waitFor(() => rendered.getByText('Rendered Id: 2'))
6001
+ expect(spy).toHaveBeenCalledTimes(1)
6002
+ })
6003
+ it('should reuse same data object reference when queryKey changes and placeholderData is present', async () => {
6004
+ const key = queryKey()
6005
+ const spy = vi.fn()
6006
+
6007
+ async function fetchNumber(id: number) {
6008
+ await sleep(5)
6009
+ return { numbers: { current: { id } } }
6010
+ }
6011
+ function Test() {
6012
+ const [id, setId] = React.useState(1)
6013
+
6014
+ const { data } = useQuery({
6015
+ select: selector,
6016
+ queryKey: [key, 'user', id],
6017
+ queryFn: () => fetchNumber(id),
6018
+ placeholderData: { numbers: { current: { id: 99 } } },
6019
+ })
6020
+
6021
+ React.useEffect(() => {
6022
+ spy(data)
6023
+ }, [data])
6024
+
6025
+ return (
6026
+ <div>
6027
+ <button name="1" onClick={() => setId(1)}>
6028
+ 1
6029
+ </button>
6030
+ <button name="2" onClick={() => setId(2)}>
6031
+ 2
6032
+ </button>
6033
+ <span>Rendered Id: {data?.id}</span>
6034
+ </div>
6035
+ )
6036
+ }
6037
+
6038
+ function selector(data: any) {
6039
+ return data.numbers.current
6040
+ }
6041
+
6042
+ const rendered = renderWithClient(queryClient, <Test />)
6043
+ expect(spy).toHaveBeenCalledTimes(1)
6044
+
6045
+ spy.mockClear()
6046
+ await waitFor(() => rendered.getByText('Rendered Id: 99'))
6047
+ await waitFor(() => rendered.getByText('Rendered Id: 1'))
6048
+ expect(spy).toHaveBeenCalledTimes(1)
6049
+
6050
+ spy.mockClear()
6051
+ fireEvent.click(rendered.getByRole('button', { name: /2/ }))
6052
+ await waitFor(() => rendered.getByText('Rendered Id: 99'))
6053
+ await waitFor(() => rendered.getByText('Rendered Id: 2'))
6054
+ expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed
6055
+
6056
+ spy.mockClear()
6057
+ fireEvent.click(rendered.getByRole('button', { name: /1/ }))
6058
+ await waitFor(() => rendered.getByText('Rendered Id: 1'))
6059
+ expect(spy).toHaveBeenCalledTimes(1)
6060
+
6061
+ spy.mockClear()
6062
+ fireEvent.click(rendered.getByRole('button', { name: /2/ }))
6063
+ await waitFor(() => rendered.getByText('Rendered Id: 2'))
6064
+ expect(spy).toHaveBeenCalledTimes(1)
6065
+ })
6088
6066
  })