@tanstack/react-query 4.29.11 → 4.29.13

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.
@@ -37,7 +37,7 @@ const transformQueryClientUsages = ({ jscodeshift, utils, root, filePath }) => {
37
37
  'removeQueries',
38
38
  'resetQueries',
39
39
  ],
40
- replacer
40
+ replacer,
41
41
  )
42
42
  }
43
43
 
@@ -61,7 +61,7 @@ const transformUseQueriesUsages = ({ jscodeshift, utils, root }) => {
61
61
  jscodeshift.property(
62
62
  'init',
63
63
  jscodeshift.identifier('queries'),
64
- node.original.arguments[0]
64
+ node.original.arguments[0],
65
65
  ),
66
66
  ]),
67
67
  ])
@@ -96,7 +96,7 @@ const transformUseQueryLikeUsages = ({
96
96
  root,
97
97
  filePath,
98
98
  keyName: 'queryKey',
99
- })
99
+ }),
100
100
  )
101
101
  transformer.execute(
102
102
  ['useMutation'],
@@ -105,7 +105,7 @@ const transformUseQueryLikeUsages = ({
105
105
  root,
106
106
  filePath,
107
107
  keyName: 'mutationKey',
108
- })
108
+ }),
109
109
  )
110
110
  }
111
111
 
@@ -1,7 +1,7 @@
1
1
  module.exports = ({ root, jscodeshift }) => {
2
2
  const findImportIdentifierOf = (importSpecifiers, identifier) => {
3
3
  const specifier = importSpecifiers
4
- .filter(node => node.value.imported.name === identifier)
4
+ .filter((node) => node.value.imported.name === identifier)
5
5
  .paths()
6
6
 
7
7
  if (specifier.length > 0) {
@@ -20,7 +20,7 @@ module.exports = ({ root, jscodeshift }) => {
20
20
  })
21
21
  .find(jscodeshift.ImportSpecifier, {})
22
22
 
23
- const locateImports = identifiers => {
23
+ const locateImports = (identifiers) => {
24
24
  const findNamespaceImportIdentifier = () => {
25
25
  const specifier = root
26
26
  .find(jscodeshift.ImportDeclaration, {
@@ -59,7 +59,7 @@ module.exports = ({ root, jscodeshift }) => {
59
59
  for (const identifier of identifiers) {
60
60
  identifierMap[identifier] = findImportIdentifierOf(
61
61
  importSpecifiers,
62
- identifier
62
+ identifier,
63
63
  )
64
64
  }
65
65
 
@@ -81,21 +81,21 @@ module.exports = ({ root, jscodeshift }) => {
81
81
  },
82
82
  })
83
83
 
84
- const findQueryClientIdentifiers = importIdentifiers =>
84
+ const findQueryClientIdentifiers = (importIdentifiers) =>
85
85
  root
86
86
  .find(jscodeshift.VariableDeclarator, {})
87
- .filter(node => {
87
+ .filter((node) => {
88
88
  if (node.value.init) {
89
89
  const initializer = node.value.init
90
90
 
91
91
  return (
92
92
  isClassInstantiationOf(
93
93
  initializer,
94
- getSelectorByImports(importIdentifiers, 'QueryClient')
94
+ getSelectorByImports(importIdentifiers, 'QueryClient'),
95
95
  ) ||
96
96
  isFunctionCallOf(
97
97
  initializer,
98
- getSelectorByImports(importIdentifiers, 'useQueryClient')
98
+ getSelectorByImports(importIdentifiers, 'useQueryClient'),
99
99
  )
100
100
  )
101
101
  }
@@ -103,18 +103,18 @@ module.exports = ({ root, jscodeshift }) => {
103
103
  return false
104
104
  })
105
105
  .paths()
106
- .map(node => node.value.id.name)
106
+ .map((node) => node.value.id.name)
107
107
 
108
- const isCallExpression = node =>
108
+ const isCallExpression = (node) =>
109
109
  jscodeshift.match(node, { type: jscodeshift.CallExpression.name })
110
110
 
111
- const isIdentifier = node =>
111
+ const isIdentifier = (node) =>
112
112
  jscodeshift.match(node, { type: jscodeshift.Identifier.name })
113
113
 
114
- const isMemberExpression = node =>
114
+ const isMemberExpression = (node) =>
115
115
  jscodeshift.match(node, { type: jscodeshift.MemberExpression.name })
116
116
 
117
- const isNewExpression = node =>
117
+ const isNewExpression = (node) =>
118
118
  jscodeshift.match(node, { type: jscodeshift.NewExpression.name })
119
119
 
120
120
  const isClassInstantiationOf = (node, selector) => {
@@ -2,17 +2,17 @@
2
2
  const UnprocessableKeyError = require('../unprocessable-key-error')
3
3
 
4
4
  module.exports = ({ jscodeshift, root, filePath, keyName = 'queryKey' }) => {
5
- const isArrayExpression = node =>
5
+ const isArrayExpression = (node) =>
6
6
  jscodeshift.match(node, { type: jscodeshift.ArrayExpression.name })
7
7
 
8
- const isStringLiteral = node =>
8
+ const isStringLiteral = (node) =>
9
9
  jscodeshift.match(node, { type: jscodeshift.StringLiteral.name }) ||
10
10
  jscodeshift.match(node, { type: jscodeshift.Literal.name })
11
11
 
12
- const isTemplateLiteral = node =>
12
+ const isTemplateLiteral = (node) =>
13
13
  jscodeshift.match(node, { type: jscodeshift.TemplateLiteral.name })
14
14
 
15
- const findVariableDeclaration = node => {
15
+ const findVariableDeclaration = (node) => {
16
16
  const declarations = root
17
17
  .find(jscodeshift.VariableDeclarator, {
18
18
  id: {
@@ -25,7 +25,7 @@ module.exports = ({ jscodeshift, root, filePath, keyName = 'queryKey' }) => {
25
25
  return declarations.length > 0 ? declarations[0] : null
26
26
  }
27
27
 
28
- const createKeyValue = node => {
28
+ const createKeyValue = (node) => {
29
29
  // When the node is a string literal we convert it into an array of strings.
30
30
  if (isStringLiteral(node)) {
31
31
  return jscodeshift.arrayExpression([
@@ -47,7 +47,7 @@ module.exports = ({ jscodeshift, root, filePath, keyName = 'queryKey' }) => {
47
47
 
48
48
  if (!variableDeclaration) {
49
49
  throw new UnprocessableKeyError(
50
- `In file ${filePath} at line ${node.loc.start.line} the type of identifier \`${node.name}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.`
50
+ `In file ${filePath} at line ${node.loc.start.line} the type of identifier \`${node.name}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.`,
51
51
  )
52
52
  }
53
53
 
@@ -60,20 +60,20 @@ module.exports = ({ jscodeshift, root, filePath, keyName = 'queryKey' }) => {
60
60
  }
61
61
 
62
62
  throw new UnprocessableKeyError(
63
- `In file ${filePath} at line ${node.loc.start.line} the type of the \`${keyName}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.`
63
+ `In file ${filePath} at line ${node.loc.start.line} the type of the \`${keyName}\` couldn't be recognized, so the codemod couldn't be applied. Please migrate manually.`,
64
64
  )
65
65
  }
66
66
 
67
- const createKeyProperty = node =>
67
+ const createKeyProperty = (node) =>
68
68
  jscodeshift.property(
69
69
  'init',
70
70
  jscodeshift.identifier(keyName),
71
- createKeyValue(node)
71
+ createKeyValue(node),
72
72
  )
73
73
 
74
74
  const getPropertyFromObjectExpression = (objectExpression, propertyName) =>
75
75
  objectExpression.properties.find(
76
- property => property.key.name === propertyName
76
+ (property) => property.key.name === propertyName,
77
77
  ) ?? null
78
78
 
79
79
  const buildWithTypeArguments = (node, builder) => {
@@ -110,27 +110,27 @@ module.exports = ({ jscodeshift, root, filePath, keyName = 'queryKey' }) => {
110
110
  ) {
111
111
  const originalKey = getPropertyFromObjectExpression(
112
112
  firstArgument,
113
- keyName
113
+ keyName,
114
114
  )
115
115
 
116
116
  if (!originalKey) {
117
117
  throw new UnprocessableKeyError(
118
- `In file ${filePath} at line ${node.loc.start.line} the \`${keyName}\` couldn't be found. Did you forget to add it?`
118
+ `In file ${filePath} at line ${node.loc.start.line} the \`${keyName}\` couldn't be found. Did you forget to add it?`,
119
119
  )
120
120
  }
121
121
 
122
122
  const restOfTheProperties = firstArgument.properties.filter(
123
- item => item.key.name !== keyName
123
+ (item) => item.key.name !== keyName,
124
124
  )
125
125
 
126
- return buildWithTypeArguments(node, originalNode =>
126
+ return buildWithTypeArguments(node, (originalNode) =>
127
127
  jscodeshift.callExpression(originalNode.original.callee, [
128
128
  jscodeshift.objectExpression([
129
129
  createKeyProperty(originalKey.value),
130
130
  ...restOfTheProperties,
131
131
  ]),
132
132
  ...restOfTheArguments,
133
- ])
133
+ ]),
134
134
  )
135
135
  }
136
136
 
@@ -139,11 +139,11 @@ module.exports = ({ jscodeshift, root, filePath, keyName = 'queryKey' }) => {
139
139
  return node
140
140
  }
141
141
 
142
- return buildWithTypeArguments(node, originalNode =>
142
+ return buildWithTypeArguments(node, (originalNode) =>
143
143
  jscodeshift.callExpression(originalNode.original.callee, [
144
144
  createKeyValue(firstArgument),
145
145
  ...restOfTheArguments,
146
- ])
146
+ ]),
147
147
  )
148
148
  } catch (error) {
149
149
  if (error.name === 'UnprocessableKeyError') {
@@ -2,15 +2,15 @@ module.exports = ({ jscodeshift, utils, root }) => {
2
2
  const isGetQueryCacheMethodCall = (
3
3
  initializer,
4
4
  importIdentifiers,
5
- knownQueryClientIds
5
+ knownQueryClientIds,
6
6
  ) => {
7
- const isKnownQueryClient = node =>
7
+ const isKnownQueryClient = (node) =>
8
8
  utils.isIdentifier(node) && knownQueryClientIds.includes(node.name)
9
9
 
10
- const isGetQueryCacheIdentifier = node =>
10
+ const isGetQueryCacheIdentifier = (node) =>
11
11
  utils.isIdentifier(node) && node.name === 'getQueryCache'
12
12
 
13
- const isValidInitializer = node =>
13
+ const isValidInitializer = (node) =>
14
14
  utils.isCallExpression(node) && utils.isMemberExpression(node.callee)
15
15
 
16
16
  if (isValidInitializer(initializer)) {
@@ -21,7 +21,7 @@ module.exports = ({ jscodeshift, utils, root }) => {
21
21
  (isKnownQueryClient(instance) ||
22
22
  utils.isFunctionCallOf(
23
23
  instance,
24
- utils.getSelectorByImports(importIdentifiers, 'useQueryClient')
24
+ utils.getSelectorByImports(importIdentifiers, 'useQueryClient'),
25
25
  ))
26
26
  )
27
27
  }
@@ -31,21 +31,21 @@ module.exports = ({ jscodeshift, utils, root }) => {
31
31
 
32
32
  const findQueryCacheInstantiations = (
33
33
  importIdentifiers,
34
- knownQueryClientIds
34
+ knownQueryClientIds,
35
35
  ) =>
36
- root.find(jscodeshift.VariableDeclarator, {}).filter(node => {
36
+ root.find(jscodeshift.VariableDeclarator, {}).filter((node) => {
37
37
  if (node.value.init) {
38
38
  const initializer = node.value.init
39
39
 
40
40
  return (
41
41
  utils.isClassInstantiationOf(
42
42
  initializer,
43
- utils.getSelectorByImports(importIdentifiers, 'QueryCache')
43
+ utils.getSelectorByImports(importIdentifiers, 'QueryCache'),
44
44
  ) ||
45
45
  isGetQueryCacheMethodCall(
46
46
  initializer,
47
47
  importIdentifiers,
48
- knownQueryClientIds
48
+ knownQueryClientIds,
49
49
  )
50
50
  )
51
51
  }
@@ -53,35 +53,36 @@ module.exports = ({ jscodeshift, utils, root }) => {
53
53
  return false
54
54
  })
55
55
 
56
- const filterQueryCacheMethodCalls = node =>
56
+ const filterQueryCacheMethodCalls = (node) =>
57
57
  utils.isIdentifier(node) && ['find', 'findAll'].includes(node.name)
58
58
 
59
- const findQueryCacheMethodCalls = importIdentifiers => {
59
+ const findQueryCacheMethodCalls = (importIdentifiers) => {
60
60
  /**
61
61
  * Here we collect all query client instantiations. We have to make aware of them because the query cache can be
62
62
  * accessed by the query client as well.
63
63
  */
64
- const queryClientIdentifiers = utils.queryClient.findQueryClientIdentifiers(
65
- importIdentifiers
66
- )
64
+ const queryClientIdentifiers =
65
+ utils.queryClient.findQueryClientIdentifiers(importIdentifiers)
67
66
  /**
68
67
  * Here we collect all query cache instantiations. The reason is simple: the methods can be called on query cache
69
68
  * instances, to locate the possible usages we need to be aware of the identifier names.
70
69
  */
71
70
  const queryCacheIdentifiers = findQueryCacheInstantiations(
72
71
  importIdentifiers,
73
- queryClientIdentifiers
72
+ queryClientIdentifiers,
74
73
  )
75
74
  .paths()
76
- .map(node => node.value.id.name)
75
+ .map((node) => node.value.id.name)
77
76
 
78
77
  return (
79
78
  utils
80
79
  // First, we need to find all method calls.
81
80
  .findAllMethodCalls()
82
81
  // Then we narrow the collection to all `fetch` and `fetchAll` methods.
83
- .filter(node => filterQueryCacheMethodCalls(node.value.callee.property))
84
- .filter(node => {
82
+ .filter((node) =>
83
+ filterQueryCacheMethodCalls(node.value.callee.property),
84
+ )
85
+ .filter((node) => {
85
86
  const object = node.value.callee.object
86
87
 
87
88
  // If the method is called on a `QueryCache` instance, we keep it in the collection.
@@ -94,7 +95,7 @@ module.exports = ({ jscodeshift, utils, root }) => {
94
95
  return isGetQueryCacheMethodCall(
95
96
  object,
96
97
  importIdentifiers,
97
- queryClientIdentifiers
98
+ queryClientIdentifiers,
98
99
  )
99
100
  }
100
101
 
@@ -103,9 +104,9 @@ module.exports = ({ jscodeshift, utils, root }) => {
103
104
  )
104
105
  }
105
106
 
106
- const execute = replacer => {
107
+ const execute = (replacer) => {
107
108
  findQueryCacheMethodCalls(
108
- utils.locateImports(['QueryCache', 'QueryClient', 'useQueryClient'])
109
+ utils.locateImports(['QueryCache', 'QueryClient', 'useQueryClient']),
109
110
  ).replaceWith(replacer)
110
111
  }
111
112
 
@@ -7,19 +7,18 @@ module.exports = ({ jscodeshift, utils, root }) => {
7
7
  * Here we collect all query client instantiations. We have to make aware of them because some method calls might
8
8
  * be invoked on these instances.
9
9
  */
10
- const queryClientIdentifiers = utils.queryClient.findQueryClientIdentifiers(
11
- importIdentifiers
12
- )
10
+ const queryClientIdentifiers =
11
+ utils.queryClient.findQueryClientIdentifiers(importIdentifiers)
13
12
 
14
13
  return (
15
14
  utils
16
15
  // First, we need to find all method calls.
17
16
  .findAllMethodCalls()
18
17
  // Then we narrow the collection to `QueryClient` methods.
19
- .filter(node =>
20
- filterQueryClientMethodCalls(node.value.callee.property, methods)
18
+ .filter((node) =>
19
+ filterQueryClientMethodCalls(node.value.callee.property, methods),
21
20
  )
22
- .filter(node => {
21
+ .filter((node) => {
23
22
  const object = node.value.callee.object
24
23
 
25
24
  // If the method is called on a `QueryClient` instance, we keep it in the collection.
@@ -30,7 +29,7 @@ module.exports = ({ jscodeshift, utils, root }) => {
30
29
  // If the method is called on the return value of `useQueryClient` hook, we keep it in the collection.
31
30
  return utils.isFunctionCallOf(
32
31
  object,
33
- utils.getSelectorByImports(importIdentifiers, 'useQueryClient')
32
+ utils.getSelectorByImports(importIdentifiers, 'useQueryClient'),
34
33
  )
35
34
  })
36
35
  )
@@ -39,7 +38,7 @@ module.exports = ({ jscodeshift, utils, root }) => {
39
38
  const execute = (methods, replacer) => {
40
39
  findQueryClientMethodCalls(
41
40
  utils.locateImports(['QueryClient', 'useQueryClient']),
42
- methods
41
+ methods,
43
42
  ).replaceWith(replacer)
44
43
  }
45
44
 
@@ -16,13 +16,13 @@ module.exports = ({ jscodeshift, utils, root }) => {
16
16
  // First, we need to find all call expressions.
17
17
  .find(jscodeshift.CallExpression, {})
18
18
  // Then we narrow the collection to the `useQuery` like hook calls.
19
- .filter(node =>
20
- filterUseQueryLikeHookCalls(node.value, importIdentifiers, hooks)
19
+ .filter((node) =>
20
+ filterUseQueryLikeHookCalls(node.value, importIdentifiers, hooks),
21
21
  )
22
22
 
23
23
  const execute = (hooks, replacer) => {
24
24
  findUseQueryLikeHookCalls(utils.locateImports(hooks), hooks).replaceWith(
25
- replacer
25
+ replacer,
26
26
  )
27
27
  }
28
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-query",
3
- "version": "4.29.11",
3
+ "version": "4.29.13",
4
4
  "description": "Hooks for managing, caching and syncing asynchronous and remote data in React",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -5887,4 +5887,37 @@ describe('useQuery', () => {
5887
5887
  fireEvent.click(fetchBtn)
5888
5888
  await waitFor(() => rendered.getByText('data: 3'))
5889
5889
  })
5890
+
5891
+ it('should be notified of updates between create and subscribe', async () => {
5892
+ const key = queryKey()
5893
+
5894
+ function Page() {
5895
+ const mounted = React.useRef<boolean>(false)
5896
+ const { data, status } = useQuery({
5897
+ enabled: false,
5898
+ queryKey: key,
5899
+ queryFn: async () => {
5900
+ await sleep(10)
5901
+ return 5
5902
+ },
5903
+ })
5904
+
5905
+ // this simulates a synchronous update between the time the query is created
5906
+ // and the time it is subscribed to that could be missed otherwise
5907
+ if (!mounted.current) {
5908
+ mounted.current = true
5909
+ queryClient.setQueryData(key, 1)
5910
+ }
5911
+
5912
+ return (
5913
+ <div>
5914
+ <span>status: {status}</span>
5915
+ <span>data: {data}</span>
5916
+ </div>
5917
+ )
5918
+ }
5919
+ const rendered = renderWithClient(queryClient, <Page />)
5920
+ await waitFor(() => rendered.getByText('status: success'))
5921
+ await waitFor(() => rendered.getByText('data: 1'))
5922
+ })
5890
5923
  })
@@ -77,10 +77,17 @@ export function useBaseQuery<
77
77
 
78
78
  useSyncExternalStore(
79
79
  React.useCallback(
80
- (onStoreChange) =>
81
- isRestoring
80
+ (onStoreChange) => {
81
+ const unsubscribe = isRestoring
82
82
  ? () => undefined
83
- : observer.subscribe(notifyManager.batchCalls(onStoreChange)),
83
+ : observer.subscribe(notifyManager.batchCalls(onStoreChange))
84
+
85
+ // Update result to make sure we did not miss any query updates
86
+ // between creating the observer and subscribing to it.
87
+ observer.updateResult()
88
+
89
+ return unsubscribe
90
+ },
84
91
  [observer, isRestoring],
85
92
  ),
86
93
  () => observer.getCurrentResult(),