@tanstack/query-core 5.0.0-alpha.6 → 5.0.0-alpha.63

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 (286) hide show
  1. package/build/lib/_virtual/{_rollupPluginBabelHelpers.js → _rollupPluginBabelHelpers.legacy.cjs} +1 -1
  2. package/build/lib/_virtual/_rollupPluginBabelHelpers.legacy.cjs.map +1 -0
  3. package/build/lib/_virtual/{_rollupPluginBabelHelpers.esm.js → _rollupPluginBabelHelpers.legacy.js} +1 -1
  4. package/build/lib/_virtual/_rollupPluginBabelHelpers.legacy.js.map +1 -0
  5. package/build/lib/{focusManager.mjs → focusManager.cjs} +9 -6
  6. package/build/lib/{focusManager.mjs.map → focusManager.cjs.map} +1 -1
  7. package/build/lib/focusManager.d.ts +2 -1
  8. package/build/lib/focusManager.d.ts.map +1 -0
  9. package/build/lib/focusManager.js +20 -39
  10. package/build/lib/focusManager.js.map +1 -1
  11. package/build/lib/focusManager.legacy.cjs +90 -0
  12. package/build/lib/focusManager.legacy.cjs.map +1 -0
  13. package/build/lib/{focusManager.esm.js → focusManager.legacy.js} +4 -4
  14. package/build/lib/focusManager.legacy.js.map +1 -0
  15. package/build/lib/{hydration.mjs → hydration.cjs} +11 -20
  16. package/build/lib/hydration.cjs.map +1 -0
  17. package/build/lib/hydration.d.ts +3 -6
  18. package/build/lib/hydration.d.ts.map +1 -0
  19. package/build/lib/hydration.js +7 -28
  20. package/build/lib/hydration.js.map +1 -1
  21. package/build/lib/hydration.legacy.cjs +92 -0
  22. package/build/lib/hydration.legacy.cjs.map +1 -0
  23. package/build/lib/{hydration.esm.js → hydration.legacy.js} +6 -19
  24. package/build/lib/hydration.legacy.js.map +1 -0
  25. package/build/lib/index.cjs +40 -0
  26. package/build/lib/index.cjs.map +1 -0
  27. package/build/lib/index.d.ts +5 -3
  28. package/build/lib/index.d.ts.map +1 -0
  29. package/build/lib/index.js +13 -39
  30. package/build/lib/index.js.map +1 -1
  31. package/build/lib/index.legacy.cjs +40 -0
  32. package/build/lib/index.legacy.cjs.map +1 -0
  33. package/build/lib/index.legacy.js +14 -0
  34. package/build/lib/index.legacy.js.map +1 -0
  35. package/build/lib/{infiniteQueryBehavior.mjs → infiniteQueryBehavior.cjs} +8 -4
  36. package/build/lib/{infiniteQueryBehavior.mjs.map → infiniteQueryBehavior.cjs.map} +1 -1
  37. package/build/lib/infiniteQueryBehavior.d.ts +1 -0
  38. package/build/lib/infiniteQueryBehavior.d.ts.map +1 -0
  39. package/build/lib/infiniteQueryBehavior.js +7 -12
  40. package/build/lib/infiniteQueryBehavior.js.map +1 -1
  41. package/build/lib/infiniteQueryBehavior.legacy.cjs +131 -0
  42. package/build/lib/infiniteQueryBehavior.legacy.cjs.map +1 -0
  43. package/build/lib/{infiniteQueryBehavior.esm.js → infiniteQueryBehavior.legacy.js} +2 -2
  44. package/build/lib/infiniteQueryBehavior.legacy.js.map +1 -0
  45. package/build/lib/{infiniteQueryObserver.mjs → infiniteQueryObserver.cjs} +11 -9
  46. package/build/lib/{infiniteQueryObserver.mjs.map → infiniteQueryObserver.cjs.map} +1 -1
  47. package/build/lib/infiniteQueryObserver.d.ts +2 -1
  48. package/build/lib/infiniteQueryObserver.d.ts.map +1 -0
  49. package/build/lib/infiniteQueryObserver.js +10 -13
  50. package/build/lib/infiniteQueryObserver.js.map +1 -1
  51. package/build/lib/infiniteQueryObserver.legacy.cjs +78 -0
  52. package/build/lib/infiniteQueryObserver.legacy.cjs.map +1 -0
  53. package/build/lib/{infiniteQueryObserver.esm.js → infiniteQueryObserver.legacy.js} +3 -3
  54. package/build/lib/infiniteQueryObserver.legacy.js.map +1 -0
  55. package/build/lib/{mutation.mjs → mutation.cjs} +13 -10
  56. package/build/lib/mutation.cjs.map +1 -0
  57. package/build/lib/mutation.d.ts +2 -1
  58. package/build/lib/mutation.d.ts.map +1 -0
  59. package/build/lib/mutation.js +107 -135
  60. package/build/lib/mutation.js.map +1 -1
  61. package/build/lib/mutation.legacy.cjs +262 -0
  62. package/build/lib/mutation.legacy.cjs.map +1 -0
  63. package/build/lib/{mutation.esm.js → mutation.legacy.js} +6 -6
  64. package/build/lib/mutation.legacy.js.map +1 -0
  65. package/build/lib/{mutationCache.mjs → mutationCache.cjs} +21 -18
  66. package/build/lib/mutationCache.cjs.map +1 -0
  67. package/build/lib/mutationCache.d.ts +3 -2
  68. package/build/lib/mutationCache.d.ts.map +1 -0
  69. package/build/lib/mutationCache.js +33 -47
  70. package/build/lib/mutationCache.js.map +1 -1
  71. package/build/lib/mutationCache.legacy.cjs +98 -0
  72. package/build/lib/mutationCache.legacy.cjs.map +1 -0
  73. package/build/lib/{mutationCache.esm.js → mutationCache.legacy.js} +11 -10
  74. package/build/lib/mutationCache.legacy.js.map +1 -0
  75. package/build/lib/{mutationObserver.mjs → mutationObserver.cjs} +13 -11
  76. package/build/lib/mutationObserver.cjs.map +1 -0
  77. package/build/lib/mutationObserver.d.ts +2 -1
  78. package/build/lib/mutationObserver.d.ts.map +1 -0
  79. package/build/lib/mutationObserver.js +59 -91
  80. package/build/lib/mutationObserver.js.map +1 -1
  81. package/build/lib/mutationObserver.legacy.cjs +128 -0
  82. package/build/lib/mutationObserver.legacy.cjs.map +1 -0
  83. package/build/lib/{mutationObserver.esm.js → mutationObserver.legacy.js} +7 -7
  84. package/build/lib/mutationObserver.legacy.js.map +1 -0
  85. package/build/lib/{notifyManager.mjs → notifyManager.cjs} +8 -5
  86. package/build/lib/{notifyManager.mjs.map → notifyManager.cjs.map} +1 -1
  87. package/build/lib/notifyManager.d.ts +4 -3
  88. package/build/lib/notifyManager.d.ts.map +1 -0
  89. package/build/lib/notifyManager.js +4 -7
  90. package/build/lib/notifyManager.js.map +1 -1
  91. package/build/lib/notifyManager.legacy.cjs +92 -0
  92. package/build/lib/notifyManager.legacy.cjs.map +1 -0
  93. package/build/lib/{notifyManager.esm.js → notifyManager.legacy.js} +2 -2
  94. package/build/lib/notifyManager.legacy.js.map +1 -0
  95. package/build/lib/{onlineManager.mjs → onlineManager.cjs} +16 -10
  96. package/build/lib/onlineManager.cjs.map +1 -0
  97. package/build/lib/onlineManager.d.ts +2 -1
  98. package/build/lib/onlineManager.d.ts.map +1 -0
  99. package/build/lib/onlineManager.js +26 -41
  100. package/build/lib/onlineManager.js.map +1 -1
  101. package/build/lib/onlineManager.legacy.cjs +94 -0
  102. package/build/lib/onlineManager.legacy.cjs.map +1 -0
  103. package/build/lib/{onlineManager.esm.js → onlineManager.legacy.js} +11 -8
  104. package/build/lib/onlineManager.legacy.js.map +1 -0
  105. package/build/lib/{queriesObserver.mjs → queriesObserver.cjs} +51 -26
  106. package/build/lib/queriesObserver.cjs.map +1 -0
  107. package/build/lib/queriesObserver.d.ts +14 -6
  108. package/build/lib/queriesObserver.d.ts.map +1 -0
  109. package/build/lib/queriesObserver.js +99 -107
  110. package/build/lib/queriesObserver.js.map +1 -1
  111. package/build/lib/queriesObserver.legacy.cjs +207 -0
  112. package/build/lib/queriesObserver.legacy.cjs.map +1 -0
  113. package/build/lib/{queriesObserver.esm.js → queriesObserver.legacy.js} +62 -22
  114. package/build/lib/queriesObserver.legacy.js.map +1 -0
  115. package/build/lib/{query.mjs → query.cjs} +22 -20
  116. package/build/lib/query.cjs.map +1 -0
  117. package/build/lib/query.d.ts +3 -2
  118. package/build/lib/query.d.ts.map +1 -0
  119. package/build/lib/query.js +173 -224
  120. package/build/lib/query.js.map +1 -1
  121. package/build/lib/query.legacy.cjs +471 -0
  122. package/build/lib/query.legacy.cjs.map +1 -0
  123. package/build/lib/{query.esm.js → query.legacy.js} +10 -10
  124. package/build/lib/query.legacy.js.map +1 -0
  125. package/build/lib/{queryCache.mjs → queryCache.cjs} +28 -23
  126. package/build/lib/queryCache.cjs.map +1 -0
  127. package/build/lib/queryCache.d.ts +3 -3
  128. package/build/lib/queryCache.d.ts.map +1 -0
  129. package/build/lib/queryCache.js +31 -37
  130. package/build/lib/queryCache.js.map +1 -1
  131. package/build/lib/queryCache.legacy.cjs +111 -0
  132. package/build/lib/queryCache.legacy.cjs.map +1 -0
  133. package/build/lib/{queryCache.esm.js → queryCache.legacy.js} +13 -12
  134. package/build/lib/queryCache.legacy.js.map +1 -0
  135. package/build/lib/{queryClient.mjs → queryClient.cjs} +50 -42
  136. package/build/lib/queryClient.cjs.map +1 -0
  137. package/build/lib/queryClient.d.ts +2 -2
  138. package/build/lib/queryClient.d.ts.map +1 -0
  139. package/build/lib/queryClient.js +98 -134
  140. package/build/lib/queryClient.js.map +1 -1
  141. package/build/lib/queryClient.legacy.cjs +322 -0
  142. package/build/lib/queryClient.legacy.cjs.map +1 -0
  143. package/build/lib/{queryClient.esm.js → queryClient.legacy.js} +28 -25
  144. package/build/lib/queryClient.legacy.js.map +1 -0
  145. package/build/lib/{queryObserver.mjs → queryObserver.cjs} +40 -50
  146. package/build/lib/queryObserver.cjs.map +1 -0
  147. package/build/lib/queryObserver.d.ts +6 -7
  148. package/build/lib/queryObserver.d.ts.map +1 -0
  149. package/build/lib/queryObserver.js +208 -323
  150. package/build/lib/queryObserver.js.map +1 -1
  151. package/build/lib/queryObserver.legacy.cjs +526 -0
  152. package/build/lib/queryObserver.legacy.cjs.map +1 -0
  153. package/build/lib/{queryObserver.esm.js → queryObserver.legacy.js} +71 -88
  154. package/build/lib/queryObserver.legacy.js.map +1 -0
  155. package/build/lib/{removable.mjs → removable.cjs} +7 -5
  156. package/build/lib/{removable.mjs.map → removable.cjs.map} +1 -1
  157. package/build/lib/removable.d.ts +1 -0
  158. package/build/lib/removable.d.ts.map +1 -0
  159. package/build/lib/removable.js +9 -18
  160. package/build/lib/removable.js.map +1 -1
  161. package/build/lib/removable.legacy.cjs +38 -0
  162. package/build/lib/removable.legacy.cjs.map +1 -0
  163. package/build/lib/{removable.esm.js → removable.legacy.js} +3 -3
  164. package/build/lib/removable.legacy.js.map +1 -0
  165. package/build/lib/{retryer.mjs → retryer.cjs} +15 -8
  166. package/build/lib/{retryer.mjs.map → retryer.cjs.map} +1 -1
  167. package/build/lib/retryer.d.ts +5 -4
  168. package/build/lib/retryer.d.ts.map +1 -0
  169. package/build/lib/retryer.js +21 -25
  170. package/build/lib/retryer.js.map +1 -1
  171. package/build/lib/retryer.legacy.cjs +158 -0
  172. package/build/lib/retryer.legacy.cjs.map +1 -0
  173. package/build/lib/{retryer.esm.js → retryer.legacy.js} +6 -4
  174. package/build/lib/retryer.legacy.js.map +1 -0
  175. package/build/lib/{subscribable.esm.js → subscribable.cjs} +8 -6
  176. package/build/lib/subscribable.cjs.map +1 -0
  177. package/build/lib/subscribable.d.ts +3 -2
  178. package/build/lib/subscribable.d.ts.map +1 -0
  179. package/build/lib/subscribable.js +5 -7
  180. package/build/lib/subscribable.js.map +1 -1
  181. package/build/lib/subscribable.legacy.cjs +28 -0
  182. package/build/lib/subscribable.legacy.cjs.map +1 -0
  183. package/build/lib/{subscribable.mjs → subscribable.legacy.js} +5 -5
  184. package/build/lib/subscribable.legacy.js.map +1 -0
  185. package/build/lib/tests/focusManager.test.d.ts +1 -0
  186. package/build/lib/tests/focusManager.test.d.ts.map +1 -0
  187. package/build/lib/tests/hydration.test.d.ts +1 -0
  188. package/build/lib/tests/hydration.test.d.ts.map +1 -0
  189. package/build/lib/tests/infiniteQueryBehavior.test.d.ts +1 -0
  190. package/build/lib/tests/infiniteQueryBehavior.test.d.ts.map +1 -0
  191. package/build/lib/tests/infiniteQueryObserver.test.d.ts +1 -0
  192. package/build/lib/tests/infiniteQueryObserver.test.d.ts.map +1 -0
  193. package/build/lib/tests/mutationCache.test.d.ts +1 -0
  194. package/build/lib/tests/mutationCache.test.d.ts.map +1 -0
  195. package/build/lib/tests/mutationObserver.test.d.ts +1 -0
  196. package/build/lib/tests/mutationObserver.test.d.ts.map +1 -0
  197. package/build/lib/tests/mutations.test.d.ts +1 -0
  198. package/build/lib/tests/mutations.test.d.ts.map +1 -0
  199. package/build/lib/tests/notifyManager.test.d.ts +1 -0
  200. package/build/lib/tests/notifyManager.test.d.ts.map +1 -0
  201. package/build/lib/tests/onlineManager.test.d.ts +1 -0
  202. package/build/lib/tests/onlineManager.test.d.ts.map +1 -0
  203. package/build/lib/tests/queriesObserver.test.d.ts +1 -0
  204. package/build/lib/tests/queriesObserver.test.d.ts.map +1 -0
  205. package/build/lib/tests/query.test.d.ts +1 -0
  206. package/build/lib/tests/query.test.d.ts.map +1 -0
  207. package/build/lib/tests/queryCache.test.d.ts +1 -0
  208. package/build/lib/tests/queryCache.test.d.ts.map +1 -0
  209. package/build/lib/tests/queryClient.test.d.ts +1 -0
  210. package/build/lib/tests/queryClient.test.d.ts.map +1 -0
  211. package/build/lib/tests/queryObserver.test.d.ts +1 -0
  212. package/build/lib/tests/queryObserver.test.d.ts.map +1 -0
  213. package/build/lib/tests/utils.d.ts +3 -2
  214. package/build/lib/tests/utils.d.ts.map +1 -0
  215. package/build/lib/tests/utils.test.d.ts +1 -0
  216. package/build/lib/tests/utils.test.d.ts.map +1 -0
  217. package/build/lib/types.d.ts +34 -46
  218. package/build/lib/types.d.ts.map +1 -0
  219. package/build/lib/{utils.mjs → utils.cjs} +23 -2
  220. package/build/lib/{utils.mjs.map → utils.cjs.map} +1 -1
  221. package/build/lib/utils.d.ts +4 -3
  222. package/build/lib/utils.d.ts.map +1 -0
  223. package/build/lib/utils.js +2 -23
  224. package/build/lib/utils.js.map +1 -1
  225. package/build/lib/utils.legacy.cjs +248 -0
  226. package/build/lib/utils.legacy.cjs.map +1 -0
  227. package/build/lib/{utils.esm.js → utils.legacy.js} +1 -1
  228. package/build/lib/utils.legacy.js.map +1 -0
  229. package/package.json +13 -9
  230. package/src/hydration.ts +18 -37
  231. package/src/index.ts +3 -4
  232. package/src/mutation.ts +1 -1
  233. package/src/mutationCache.ts +4 -4
  234. package/src/mutationObserver.ts +1 -1
  235. package/src/onlineManager.ts +8 -4
  236. package/src/queriesObserver.ts +75 -25
  237. package/src/query.ts +4 -4
  238. package/src/queryCache.ts +5 -8
  239. package/src/queryClient.ts +20 -20
  240. package/src/queryObserver.ts +47 -55
  241. package/src/subscribable.ts +5 -5
  242. package/src/tests/hydration.test.tsx +7 -3
  243. package/src/tests/query.test.tsx +1 -1
  244. package/src/tests/queryCache.test.tsx +1 -19
  245. package/src/tests/queryClient.test.tsx +39 -3
  246. package/src/tests/queryObserver.test.tsx +121 -0
  247. package/src/types.ts +14 -21
  248. package/build/lib/_virtual/_rollupPluginBabelHelpers.esm.js.map +0 -1
  249. package/build/lib/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
  250. package/build/lib/focusManager.esm.js.map +0 -1
  251. package/build/lib/hydration.esm.js.map +0 -1
  252. package/build/lib/hydration.mjs.map +0 -1
  253. package/build/lib/index.esm.js +0 -14
  254. package/build/lib/index.esm.js.map +0 -1
  255. package/build/lib/index.mjs +0 -14
  256. package/build/lib/index.mjs.map +0 -1
  257. package/build/lib/infiniteQueryBehavior.esm.js.map +0 -1
  258. package/build/lib/infiniteQueryObserver.esm.js.map +0 -1
  259. package/build/lib/mutation.esm.js.map +0 -1
  260. package/build/lib/mutation.mjs.map +0 -1
  261. package/build/lib/mutationCache.esm.js.map +0 -1
  262. package/build/lib/mutationCache.mjs.map +0 -1
  263. package/build/lib/mutationObserver.esm.js.map +0 -1
  264. package/build/lib/mutationObserver.mjs.map +0 -1
  265. package/build/lib/notifyManager.esm.js.map +0 -1
  266. package/build/lib/onlineManager.esm.js.map +0 -1
  267. package/build/lib/onlineManager.mjs.map +0 -1
  268. package/build/lib/queriesObserver.esm.js.map +0 -1
  269. package/build/lib/queriesObserver.mjs.map +0 -1
  270. package/build/lib/query.esm.js.map +0 -1
  271. package/build/lib/query.mjs.map +0 -1
  272. package/build/lib/queryCache.esm.js.map +0 -1
  273. package/build/lib/queryCache.mjs.map +0 -1
  274. package/build/lib/queryClient.esm.js.map +0 -1
  275. package/build/lib/queryClient.mjs.map +0 -1
  276. package/build/lib/queryObserver.esm.js.map +0 -1
  277. package/build/lib/queryObserver.mjs.map +0 -1
  278. package/build/lib/removable.esm.js.map +0 -1
  279. package/build/lib/retryer.esm.js.map +0 -1
  280. package/build/lib/subscribable.esm.js.map +0 -1
  281. package/build/lib/subscribable.mjs.map +0 -1
  282. package/build/lib/utils.esm.js.map +0 -1
  283. package/build/umd/index.development.js +0 -2683
  284. package/build/umd/index.development.js.map +0 -1
  285. package/build/umd/index.production.js +0 -2
  286. package/build/umd/index.production.js.map +0 -1
@@ -68,7 +68,7 @@ export class MutationObserver<
68
68
  }
69
69
 
70
70
  protected onUnsubscribe(): void {
71
- if (!this.listeners.length) {
71
+ if (!this.hasListeners()) {
72
72
  this.#currentMutation?.removeObserver(this)
73
73
  }
74
74
  }
@@ -5,6 +5,8 @@ type SetupFn = (
5
5
  setOnline: (online?: boolean) => void,
6
6
  ) => (() => void) | undefined
7
7
 
8
+ const onlineEvents = ['online', 'offline'] as const
9
+
8
10
  export class OnlineManager extends Subscribable {
9
11
  #online?: boolean
10
12
  #cleanup?: () => void
@@ -19,13 +21,15 @@ export class OnlineManager extends Subscribable {
19
21
  if (!isServer && window.addEventListener) {
20
22
  const listener = () => onOnline()
21
23
  // Listen to online
22
- window.addEventListener('online', listener, false)
23
- window.addEventListener('offline', listener, false)
24
+ onlineEvents.forEach((event) => {
25
+ window.addEventListener(event, listener, false)
26
+ })
24
27
 
25
28
  return () => {
26
29
  // Be sure to unsubscribe if a new handler is set
27
- window.removeEventListener('online', listener)
28
- window.removeEventListener('offline', listener)
30
+ onlineEvents.forEach((event) => {
31
+ window.removeEventListener(event, listener)
32
+ })
29
33
  }
30
34
  }
31
35
 
@@ -8,9 +8,10 @@ import type { QueryClient } from './queryClient'
8
8
  import type { NotifyOptions } from './queryObserver'
9
9
  import { QueryObserver } from './queryObserver'
10
10
  import { Subscribable } from './subscribable'
11
+ import { replaceEqualDeep } from './utils'
11
12
 
12
13
  function difference<T>(array1: T[], array2: T[]): T[] {
13
- return array1.filter((x) => array2.indexOf(x) === -1)
14
+ return array1.filter((x) => !array2.includes(x))
14
15
  }
15
16
 
16
17
  function replaceAt<T>(array: T[], index: number, value: T): T[] {
@@ -21,27 +22,44 @@ function replaceAt<T>(array: T[], index: number, value: T): T[] {
21
22
 
22
23
  type QueriesObserverListener = (result: QueryObserverResult[]) => void
23
24
 
24
- export class QueriesObserver extends Subscribable<QueriesObserverListener> {
25
+ export interface QueriesObserverOptions<
26
+ TCombinedResult = QueryObserverResult[],
27
+ > {
28
+ combine?: (result: QueryObserverResult[]) => TCombinedResult
29
+ }
30
+
31
+ export class QueriesObserver<
32
+ TCombinedResult = QueryObserverResult[],
33
+ > extends Subscribable<QueriesObserverListener> {
25
34
  #client: QueryClient
26
- #result: QueryObserverResult[]
35
+ #result!: QueryObserverResult[]
27
36
  #queries: QueryObserverOptions[]
28
37
  #observers: QueryObserver[]
38
+ #options?: QueriesObserverOptions<TCombinedResult>
39
+ #combinedResult!: TCombinedResult
29
40
 
30
- constructor(client: QueryClient, queries?: QueryObserverOptions[]) {
41
+ constructor(
42
+ client: QueryClient,
43
+ queries: QueryObserverOptions[],
44
+ options?: QueriesObserverOptions<TCombinedResult>,
45
+ ) {
31
46
  super()
32
47
 
33
48
  this.#client = client
34
49
  this.#queries = []
35
- this.#result = []
36
50
  this.#observers = []
37
51
 
38
- if (queries) {
39
- this.setQueries(queries)
40
- }
52
+ this.#setResult([])
53
+ this.setQueries(queries, options)
54
+ }
55
+
56
+ #setResult(value: QueryObserverResult[]) {
57
+ this.#result = value
58
+ this.#combinedResult = this.#combineResult(value)
41
59
  }
42
60
 
43
61
  protected onSubscribe(): void {
44
- if (this.listeners.length === 1) {
62
+ if (this.listeners.size === 1) {
45
63
  this.#observers.forEach((observer) => {
46
64
  observer.subscribe((result) => {
47
65
  this.#onUpdate(observer, result)
@@ -51,13 +69,13 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
51
69
  }
52
70
 
53
71
  protected onUnsubscribe(): void {
54
- if (!this.listeners.length) {
72
+ if (!this.listeners.size) {
55
73
  this.destroy()
56
74
  }
57
75
  }
58
76
 
59
77
  destroy(): void {
60
- this.listeners = []
78
+ this.listeners = new Set()
61
79
  this.#observers.forEach((observer) => {
62
80
  observer.destroy()
63
81
  })
@@ -65,9 +83,11 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
65
83
 
66
84
  setQueries(
67
85
  queries: QueryObserverOptions[],
86
+ options?: QueriesObserverOptions<TCombinedResult>,
68
87
  notifyOptions?: NotifyOptions,
69
88
  ): void {
70
89
  this.#queries = queries
90
+ this.#options = options
71
91
 
72
92
  notifyManager.batch(() => {
73
93
  const prevObservers = this.#observers
@@ -92,7 +112,7 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
92
112
  }
93
113
 
94
114
  this.#observers = newObservers
95
- this.#result = newResult
115
+ this.#setResult(newResult)
96
116
 
97
117
  if (!this.hasListeners()) {
98
118
  return
@@ -112,8 +132,8 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
112
132
  })
113
133
  }
114
134
 
115
- getCurrentResult(): QueryObserverResult[] {
116
- return this.#result
135
+ getCurrentResult(): TCombinedResult {
136
+ return this.#combinedResult
117
137
  }
118
138
 
119
139
  getQueries() {
@@ -124,38 +144,68 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
124
144
  return this.#observers
125
145
  }
126
146
 
127
- getOptimisticResult(queries: QueryObserverOptions[]): QueryObserverResult[] {
128
- return this.#findMatchingObservers(queries).map((match) =>
147
+ getOptimisticResult(
148
+ queries: QueryObserverOptions[],
149
+ ): [
150
+ rawResult: QueryObserverResult[],
151
+ combineResult: (r?: QueryObserverResult[]) => TCombinedResult,
152
+ trackResult: () => QueryObserverResult[],
153
+ ] {
154
+ const matches = this.#findMatchingObservers(queries)
155
+ const result = matches.map((match) =>
129
156
  match.observer.getOptimisticResult(match.defaultedQueryOptions),
130
157
  )
158
+
159
+ return [
160
+ result,
161
+ (r?: QueryObserverResult[]) => {
162
+ return this.#combineResult(r ?? result)
163
+ },
164
+ () => {
165
+ return matches.map((match, index) => {
166
+ const observerResult = result[index]!
167
+ return !match.defaultedQueryOptions.notifyOnChangeProps
168
+ ? match.observer.trackResult(observerResult)
169
+ : observerResult
170
+ })
171
+ },
172
+ ]
173
+ }
174
+
175
+ #combineResult(input: QueryObserverResult[]): TCombinedResult {
176
+ const combine = this.#options?.combine
177
+ if (combine) {
178
+ return replaceEqualDeep(this.#combinedResult, combine(input))
179
+ }
180
+ return input as any
131
181
  }
132
182
 
133
183
  #findMatchingObservers(
134
184
  queries: QueryObserverOptions[],
135
185
  ): QueryObserverMatch[] {
136
186
  const prevObservers = this.#observers
187
+ const prevObserversMap = new Map(
188
+ prevObservers.map((observer) => [observer.options.queryHash, observer]),
189
+ )
190
+
137
191
  const defaultedQueryOptions = queries.map((options) =>
138
192
  this.#client.defaultQueryOptions(options),
139
193
  )
140
194
 
141
195
  const matchingObservers: QueryObserverMatch[] =
142
196
  defaultedQueryOptions.flatMap((defaultedOptions) => {
143
- const match = prevObservers.find(
144
- (observer) =>
145
- observer.options.queryHash === defaultedOptions.queryHash,
146
- )
197
+ const match = prevObserversMap.get(defaultedOptions.queryHash)
147
198
  if (match != null) {
148
199
  return [{ defaultedQueryOptions: defaultedOptions, observer: match }]
149
200
  }
150
201
  return []
151
202
  })
152
203
 
153
- const matchedQueryHashes = matchingObservers.map(
154
- (match) => match.defaultedQueryOptions.queryHash,
204
+ const matchedQueryHashes = new Set(
205
+ matchingObservers.map((match) => match.defaultedQueryOptions.queryHash),
155
206
  )
156
207
  const unmatchedQueries = defaultedQueryOptions.filter(
157
- (defaultedOptions) =>
158
- !matchedQueryHashes.includes(defaultedOptions.queryHash),
208
+ (defaultedOptions) => !matchedQueryHashes.has(defaultedOptions.queryHash),
159
209
  )
160
210
 
161
211
  const getObserver = (options: QueryObserverOptions): QueryObserver => {
@@ -192,7 +242,7 @@ export class QueriesObserver extends Subscribable<QueriesObserverListener> {
192
242
  #onUpdate(observer: QueryObserver, result: QueryObserverResult): void {
193
243
  const index = this.#observers.indexOf(observer)
194
244
  if (index !== -1) {
195
- this.#result = replaceAt(this.#result, index, result)
245
+ this.#setResult(replaceAt(this.#result, index, result))
196
246
  this.#notify()
197
247
  }
198
248
  }
package/src/query.ts CHANGED
@@ -281,7 +281,7 @@ export class Query<
281
281
  }
282
282
 
283
283
  addObserver(observer: QueryObserver<any, any, any, any, any>): void {
284
- if (this.#observers.indexOf(observer) === -1) {
284
+ if (!this.#observers.includes(observer)) {
285
285
  this.#observers.push(observer)
286
286
 
287
287
  // Stop the query from being garbage collected
@@ -292,7 +292,7 @@ export class Query<
292
292
  }
293
293
 
294
294
  removeObserver(observer: QueryObserver<any, any, any, any, any>): void {
295
- if (this.#observers.indexOf(observer) !== -1) {
295
+ if (this.#observers.includes(observer)) {
296
296
  this.#observers = this.#observers.filter((x) => x !== observer)
297
297
 
298
298
  if (!this.#observers.length) {
@@ -464,7 +464,7 @@ export class Query<
464
464
  `Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ${this.queryHash}`,
465
465
  )
466
466
  }
467
- onError(new Error('undefined') as any)
467
+ onError(new Error(`${this.queryHash} data is undefined`) as any)
468
468
  return
469
469
  }
470
470
 
@@ -588,7 +588,7 @@ export class Query<
588
588
 
589
589
  notifyManager.batch(() => {
590
590
  this.#observers.forEach((observer) => {
591
- observer.onQueryUpdate(action)
591
+ observer.onQueryUpdate()
592
592
  })
593
593
 
594
594
  this.#cache.notify({ query: this, type: 'updated', action })
package/src/queryCache.ts CHANGED
@@ -27,7 +27,6 @@ interface QueryCacheConfig {
27
27
  error: DefaultError | null,
28
28
  query: Query<unknown, unknown, unknown>,
29
29
  ) => void
30
- createStore?: () => QueryStore
31
30
  }
32
31
 
33
32
  interface NotifyEventQueryAdded extends NotifyEvent {
@@ -95,7 +94,7 @@ export class QueryCache extends Subscribable<QueryCacheListener> {
95
94
 
96
95
  constructor(public config: QueryCacheConfig = {}) {
97
96
  super()
98
- this.#queries = config.createStore?.() ?? new Map<string, Query>()
97
+ this.#queries = new Map<string, Query>()
99
98
  }
100
99
 
101
100
  build<TQueryFnData, TError, TData, TQueryKey extends QueryKey>(
@@ -176,13 +175,11 @@ export class QueryCache extends Subscribable<QueryCacheListener> {
176
175
  find<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData>(
177
176
  filters: WithRequired<QueryFilters, 'queryKey'>,
178
177
  ): Query<TQueryFnData, TError, TData> | undefined {
179
- if (typeof filters.exact === 'undefined') {
180
- filters.exact = true
181
- }
178
+ const defaultedFilters = { exact: true, ...filters }
182
179
 
183
- return this.getAll().find((query) => matchQuery(filters, query)) as
184
- | Query<TQueryFnData, TError, TData>
185
- | undefined
180
+ return this.getAll().find((query) =>
181
+ matchQuery(defaultedFilters, query),
182
+ ) as Query<TQueryFnData, TError, TData> | undefined
186
183
  }
187
184
 
188
185
  findAll(filters: QueryFilters = {}): Query[] {
@@ -25,6 +25,8 @@ import type {
25
25
  ResetOptions,
26
26
  SetDataOptions,
27
27
  DefaultError,
28
+ CancelOptions,
29
+ DefaultedQueryObserverOptions,
28
30
  } from './types'
29
31
  import type { QueryState } from './query'
30
32
  import { QueryCache } from './queryCache'
@@ -33,7 +35,6 @@ import { focusManager } from './focusManager'
33
35
  import { onlineManager } from './onlineManager'
34
36
  import { notifyManager } from './notifyManager'
35
37
  import { infiniteQueryBehavior } from './infiniteQueryBehavior'
36
- import type { CancelOptions, DefaultedQueryObserverOptions } from './types'
37
38
 
38
39
  // TYPES
39
40
 
@@ -212,14 +213,12 @@ export class QueryClient {
212
213
  filters: QueryFilters = {},
213
214
  cancelOptions: CancelOptions = {},
214
215
  ): Promise<void> {
215
- if (typeof cancelOptions.revert === 'undefined') {
216
- cancelOptions.revert = true
217
- }
216
+ const defaultedCancelOptions = { revert: true, ...cancelOptions }
218
217
 
219
218
  const promises = notifyManager.batch(() =>
220
219
  this.#queryCache
221
220
  .findAll(filters)
222
- .map((query) => query.cancel(cancelOptions)),
221
+ .map((query) => query.cancel(defaultedCancelOptions)),
223
222
  )
224
223
 
225
224
  return Promise.all(promises).then(noop).catch(noop)
@@ -249,25 +248,26 @@ export class QueryClient {
249
248
  filters: RefetchQueryFilters = {},
250
249
  options?: RefetchOptions,
251
250
  ): Promise<void> {
251
+ const fetchOptions = {
252
+ ...options,
253
+ cancelRefetch: options?.cancelRefetch ?? true,
254
+ }
252
255
  const promises = notifyManager.batch(() =>
253
256
  this.#queryCache
254
257
  .findAll(filters)
255
258
  .filter((query) => !query.isDisabled())
256
- .map((query) =>
257
- query.fetch(undefined, {
258
- ...options,
259
- cancelRefetch: options?.cancelRefetch ?? true,
260
- }),
261
- ),
259
+ .map((query) => {
260
+ let promise = query.fetch(undefined, fetchOptions)
261
+ if (!fetchOptions.throwOnError) {
262
+ promise = promise.catch(noop)
263
+ }
264
+ return query.state.fetchStatus === 'paused'
265
+ ? Promise.resolve()
266
+ : promise
267
+ }),
262
268
  )
263
269
 
264
- let promise = Promise.all(promises).then(noop)
265
-
266
- if (!options?.throwOnError) {
267
- promise = promise.catch(noop)
268
- }
269
-
270
- return promise
270
+ return Promise.all(promises).then(noop)
271
271
  }
272
272
 
273
273
  fetchQuery<
@@ -480,8 +480,8 @@ export class QueryClient {
480
480
  defaultedOptions.refetchOnReconnect =
481
481
  defaultedOptions.networkMode !== 'always'
482
482
  }
483
- if (typeof defaultedOptions.throwErrors === 'undefined') {
484
- defaultedOptions.throwErrors = !!defaultedOptions.suspense
483
+ if (typeof defaultedOptions.throwOnError === 'undefined') {
484
+ defaultedOptions.throwOnError = !!defaultedOptions.suspense
485
485
  }
486
486
 
487
487
  return defaultedOptions as DefaultedQueryObserverOptions<
@@ -1,14 +1,6 @@
1
- import type { DefaultedQueryObserverOptions, DefaultError } from './types'
2
- import {
3
- isServer,
4
- isValidTimeout,
5
- noop,
6
- replaceData,
7
- shallowEqualObjects,
8
- timeUntilStale,
9
- } from './utils'
10
- import { notifyManager } from './notifyManager'
11
1
  import type {
2
+ DefaultedQueryObserverOptions,
3
+ DefaultError,
12
4
  PlaceholderDataFunction,
13
5
  QueryKey,
14
6
  QueryObserverBaseResult,
@@ -17,11 +9,20 @@ import type {
17
9
  QueryOptions,
18
10
  RefetchOptions,
19
11
  } from './types'
20
- import type { Query, QueryState, Action, FetchOptions } from './query'
12
+ import {
13
+ isServer,
14
+ isValidTimeout,
15
+ noop,
16
+ replaceData,
17
+ shallowEqualObjects,
18
+ timeUntilStale,
19
+ } from './utils'
20
+ import { notifyManager } from './notifyManager'
21
+ import type { Query, QueryState, FetchOptions } from './query'
21
22
  import type { QueryClient } from './queryClient'
22
23
  import { focusManager } from './focusManager'
23
24
  import { Subscribable } from './subscribable'
24
- import { canFetch, isCancelledError } from './retryer'
25
+ import { canFetch } from './retryer'
25
26
 
26
27
  type QueryObserverListener<TData, TError> = (
27
28
  result: QueryObserverResult<TData, TError>,
@@ -29,8 +30,6 @@ type QueryObserverListener<TData, TError> = (
29
30
 
30
31
  export interface NotifyOptions {
31
32
  listeners?: boolean
32
- onError?: boolean
33
- onSuccess?: boolean
34
33
  }
35
34
 
36
35
  export interface ObserverFetchOptions extends FetchOptions {
@@ -64,10 +63,12 @@ export class QueryObserver<
64
63
  TQueryData,
65
64
  TQueryKey
66
65
  >
67
- #previousQueryResult?: QueryObserverResult<TData, TError>
68
66
  #selectError: TError | null
69
67
  #selectFn?: (data: TQueryData) => TData
70
68
  #selectResult?: TData
69
+ // This property keeps track of the last query with defined data.
70
+ // It will be used to pass the previous data and query to the placeholder function between renders.
71
+ #lastQueryWithDefinedData?: Query<TQueryFnData, TError, TQueryData, TQueryKey>
71
72
  #staleTimeoutId?: ReturnType<typeof setTimeout>
72
73
  #refetchIntervalId?: ReturnType<typeof setInterval>
73
74
  #currentRefetchInterval?: number | false
@@ -97,7 +98,7 @@ export class QueryObserver<
97
98
  }
98
99
 
99
100
  protected onSubscribe(): void {
100
- if (this.listeners.length === 1) {
101
+ if (this.listeners.size === 1) {
101
102
  this.#currentQuery.addObserver(this)
102
103
 
103
104
  if (shouldFetchOnMount(this.#currentQuery, this.options)) {
@@ -109,7 +110,7 @@ export class QueryObserver<
109
110
  }
110
111
 
111
112
  protected onUnsubscribe(): void {
112
- if (!this.listeners.length) {
113
+ if (!this.hasListeners()) {
113
114
  this.destroy()
114
115
  }
115
116
  }
@@ -131,7 +132,7 @@ export class QueryObserver<
131
132
  }
132
133
 
133
134
  destroy(): void {
134
- this.listeners = []
135
+ this.listeners = new Set()
135
136
  this.#clearStaleTimeout()
136
137
  this.#clearRefetchInterval()
137
138
  this.#currentQuery.removeObserver(this)
@@ -190,7 +191,7 @@ export class QueryObserver<
190
191
  }
191
192
 
192
193
  // Update result
193
- this.#updateResult(notifyOptions)
194
+ this.updateResult(notifyOptions)
194
195
 
195
196
  // Update stale interval if needed
196
197
  if (
@@ -290,7 +291,7 @@ export class QueryObserver<
290
291
  ...fetchOptions,
291
292
  cancelRefetch: fetchOptions.cancelRefetch ?? true,
292
293
  }).then(() => {
293
- this.#updateResult()
294
+ this.updateResult()
294
295
  return this.#currentResult
295
296
  })
296
297
  }
@@ -336,18 +337,20 @@ export class QueryObserver<
336
337
 
337
338
  this.#staleTimeoutId = setTimeout(() => {
338
339
  if (!this.#currentResult.isStale) {
339
- this.#updateResult()
340
+ this.updateResult()
340
341
  }
341
342
  }, timeout)
342
343
  }
343
344
 
344
345
  #computeRefetchInterval() {
345
- return typeof this.options.refetchInterval === 'function'
346
- ? this.options.refetchInterval(
347
- this.#currentResult.data,
348
- this.#currentQuery,
349
- )
350
- : this.options.refetchInterval ?? false
346
+ return (
347
+ (typeof this.options.refetchInterval === 'function'
348
+ ? this.options.refetchInterval(
349
+ this.#currentResult.data,
350
+ this.#currentQuery,
351
+ )
352
+ : this.options.refetchInterval) ?? false
353
+ )
351
354
  }
352
355
 
353
356
  #updateRefetchInterval(nextInterval: number | false): void {
@@ -414,9 +417,6 @@ export class QueryObserver<
414
417
  const queryInitialState = queryChange
415
418
  ? query.state
416
419
  : this.#currentQueryInitialState
417
- const prevQueryResult = queryChange
418
- ? this.#currentResult
419
- : this.#previousQueryResult
420
420
 
421
421
  const { state } = query
422
422
  let { error, errorUpdatedAt, fetchStatus, status } = state
@@ -490,7 +490,10 @@ export class QueryObserver<
490
490
  typeof options.placeholderData === 'function'
491
491
  ? (
492
492
  options.placeholderData as unknown as PlaceholderDataFunction<TQueryData>
493
- )(prevQueryResult?.data as TQueryData | undefined)
493
+ )(
494
+ this.#lastQueryWithDefinedData?.state.data,
495
+ this.#lastQueryWithDefinedData as any,
496
+ )
494
497
  : options.placeholderData
495
498
  if (options.select && typeof placeholderData !== 'undefined') {
496
499
  try {
@@ -504,7 +507,11 @@ export class QueryObserver<
504
507
 
505
508
  if (typeof placeholderData !== 'undefined') {
506
509
  status = 'success'
507
- data = replaceData(prevResult?.data, placeholderData, options) as TData
510
+ data = replaceData(
511
+ prevResult?.data,
512
+ placeholderData as unknown,
513
+ options,
514
+ ) as TData
508
515
  isPlaceholderData = true
509
516
  }
510
517
  }
@@ -554,7 +561,7 @@ export class QueryObserver<
554
561
  return result as QueryObserverResult<TData, TError>
555
562
  }
556
563
 
557
- #updateResult(notifyOptions?: NotifyOptions): void {
564
+ updateResult(notifyOptions?: NotifyOptions): void {
558
565
  const prevResult = this.#currentResult as
559
566
  | QueryObserverResult<TData, TError>
560
567
  | undefined
@@ -568,6 +575,9 @@ export class QueryObserver<
568
575
  return
569
576
  }
570
577
 
578
+ if (this.#currentResultState.data !== undefined) {
579
+ this.#lastQueryWithDefinedData = this.#currentQuery
580
+ }
571
581
  this.#currentResult = nextResult
572
582
 
573
583
  // Determine which callbacks to trigger
@@ -589,7 +599,7 @@ export class QueryObserver<
589
599
 
590
600
  const includedProps = new Set(notifyOnChangeProps ?? this.#trackedProps)
591
601
 
592
- if (this.options.throwErrors) {
602
+ if (this.options.throwOnError) {
593
603
  includedProps.add('error')
594
604
  }
595
605
 
@@ -619,7 +629,6 @@ export class QueryObserver<
619
629
  | undefined
620
630
  this.#currentQuery = query
621
631
  this.#currentQueryInitialState = query.state
622
- this.#previousQueryResult = this.#currentResult
623
632
 
624
633
  if (this.hasListeners()) {
625
634
  prevQuery?.removeObserver(this)
@@ -627,16 +636,8 @@ export class QueryObserver<
627
636
  }
628
637
  }
629
638
 
630
- onQueryUpdate(action: Action<TData, TError>): void {
631
- const notifyOptions: NotifyOptions = {}
632
-
633
- if (action.type === 'success') {
634
- notifyOptions.onSuccess = !action.manual
635
- } else if (action.type === 'error' && !isCancelledError(action.error)) {
636
- notifyOptions.onError = true
637
- }
638
-
639
- this.#updateResult(notifyOptions)
639
+ onQueryUpdate(): void {
640
+ this.updateResult()
640
641
 
641
642
  if (this.hasListeners()) {
642
643
  this.#updateTimers()
@@ -645,16 +646,7 @@ export class QueryObserver<
645
646
 
646
647
  #notify(notifyOptions: NotifyOptions): void {
647
648
  notifyManager.batch(() => {
648
- // First trigger the configuration callbacks
649
- if (notifyOptions.onSuccess) {
650
- this.options.onSuccess?.(this.#currentResult.data!)
651
- this.options.onSettled?.(this.#currentResult.data, null)
652
- } else if (notifyOptions.onError) {
653
- this.options.onError?.(this.#currentResult.error!)
654
- this.options.onSettled?.(undefined, this.#currentResult.error)
655
- }
656
-
657
- // Then trigger the listeners
649
+ // First, trigger the listeners
658
650
  if (notifyOptions.listeners) {
659
651
  this.listeners.forEach((listener) => {
660
652
  listener(this.#currentResult)
@@ -1,26 +1,26 @@
1
1
  type Listener = () => void
2
2
 
3
3
  export class Subscribable<TListener extends Function = Listener> {
4
- protected listeners: TListener[]
4
+ protected listeners: Set<TListener>
5
5
 
6
6
  constructor() {
7
- this.listeners = []
7
+ this.listeners = new Set()
8
8
  this.subscribe = this.subscribe.bind(this)
9
9
  }
10
10
 
11
11
  subscribe(listener: TListener): () => void {
12
- this.listeners.push(listener)
12
+ this.listeners.add(listener)
13
13
 
14
14
  this.onSubscribe()
15
15
 
16
16
  return () => {
17
- this.listeners = this.listeners.filter((x) => x !== listener)
17
+ this.listeners.delete(listener)
18
18
  this.onUnsubscribe()
19
19
  }
20
20
  }
21
21
 
22
22
  hasListeners(): boolean {
23
- return this.listeners.length > 0
23
+ return this.listeners.size > 0
24
24
  }
25
25
 
26
26
  protected onSubscribe(): void {