Skip to content

Commit aa853d8

Browse files
committed
Merge remote-tracking branch 'react-query/master' into alpha
# Conflicts: # src/react/utils.ts # src/reactjs/useBaseQuery.ts # src/reactjs/useMutation.ts
2 parents ada0e34 + b44c213 commit aa853d8

File tree

10 files changed

+69
-17
lines changed

10 files changed

+69
-17
lines changed

.all-contributorsrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,15 @@
203203
"code",
204204
"doc"
205205
]
206+
},
207+
{
208+
"login": "zrwsk",
209+
"name": "Jakub Żurawski",
210+
"avatar_url": "https://avatars.githubusercontent.com/u/9089600?v=4",
211+
"profile": "https://github.com/zrwsk",
212+
"contributions": [
213+
"doc"
214+
]
206215
}
207216
],
208217
"contributorsPerLine": 7,

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
## Questions
44

5-
If you have questions about implementation details, help or support, then please use our dedicated community forum at [Github Discussions](https://github.com/tannerlinsley/react-query/discussions) **PLEASE NOTE:** If you choose to instead open an issue for your question, your issue will be immediately closed and redirected to the forum.
5+
If you have questions about implementation details, help or support, then please use our dedicated community forum at [GitHub Discussions](https://github.com/tannerlinsley/react-query/discussions) **PLEASE NOTE:** If you choose to instead open an issue for your question, your issue will be immediately closed and redirected to the forum.
66

77
## Reporting Issues
88

9-
If you have found what you think is a bug, please [file an issue](https://github.com/tannerlinsley/react-query/issues/new). **PLEASE NOTE:** Issues that are identified as implementation questions or non-issues will be immediately closed and redirected to [Github Discussions](https://github.com/tannerlinsley/react-query/discussions)
9+
If you have found what you think is a bug, please [file an issue](https://github.com/tannerlinsley/react-query/issues/new). **PLEASE NOTE:** Issues that are identified as implementation questions or non-issues will be immediately closed and redirected to [GitHub Discussions](https://github.com/tannerlinsley/react-query/discussions)
1010

1111
## Suggesting new features
1212

@@ -122,4 +122,4 @@ Use an appropriate commit type. Be especially careful with breaking changes.
122122

123123
## Releases
124124

125-
For each new commit added to `master` with `git push` or by merging a pull request or merging from another branch, a github action is triggered and runs the `semantic-release` command to make a release if there are codebase changes since the last release that affect the package functionalities.
125+
For each new commit added to `master` with `git push` or by merging a pull request or merging from another branch, a GitHub action is triggered and runs the `semantic-release` command to make a release if there are codebase changes since the last release that affect the package functionalities.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
8282
<td align="center"><a href="https://github.com/babycourageous"><img src="https://avatars.githubusercontent.com/u/14936212?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rene Dellefont</b></sub></a><br /><a href="https://github.com/tannerlinsley/react-query/commits?author=babycourageous" title="Code">💻</a> <a href="https://github.com/tannerlinsley/react-query/commits?author=babycourageous" title="Documentation">📖</a></td>
8383
<td align="center"><a href="https://github.com/jvuoti"><img src="https://avatars.githubusercontent.com/u/3702781?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Janne Vuoti</b></sub></a><br /><a href="https://github.com/tannerlinsley/react-query/commits?author=jvuoti" title="Code">💻</a></td>
8484
<td align="center"><a href="http://seaviewlab.com"><img src="https://avatars.githubusercontent.com/u/20332397?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arnaud</b></sub></a><br /><a href="https://github.com/tannerlinsley/react-query/commits?author=arnaudbzn" title="Code">💻</a> <a href="https://github.com/tannerlinsley/react-query/commits?author=arnaudbzn" title="Documentation">📖</a></td>
85+
<td align="center"><a href="https://github.com/zrwsk"><img src="https://avatars.githubusercontent.com/u/9089600?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jakub Żurawski</b></sub></a><br /><a href="https://github.com/tannerlinsley/react-query/commits?author=zrwsk" title="Documentation">📖</a></td>
8586
</tr>
8687
</table>
8788

docs/src/pages/guides/mutations.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,28 @@ mutate(todo, {
179179
})
180180
```
181181

182+
### Consecutive mutations
183+
There is a slight difference in handling `onSuccess`, `onError` and `onSettled` callbacks when it comes to consecutive mutations. When passed to the `mutate` function, they will be fired up only _once_ and only if the component is still mounted. This is due to the fact that mutation observer is removed and resubscribed every time when the `mutate` function is called. On the contrary, `useMutation` handlers execute for each `mutate` call.
184+
185+
> Be aware that most likely, `mutationFn` passed to `useMutation` is ansynchronous. In that case, the order in which mutations are fulfilled may differ from the order of `mutate` function calls.
186+
187+
```js
188+
useMutation(addTodo, {
189+
onSuccess: (data, error, variables, context) => {
190+
// Will be called 3 times
191+
},
192+
})
193+
194+
['Todo 1', 'Todo 2', 'Todo 3'].forEach((todo) => {
195+
mutate(todo, {
196+
onSuccess: (data, error, variables, context) => {
197+
// Will execute only once, for the last mutation (Todo 3),
198+
// regardles which mutation resolves first
199+
},
200+
})
201+
})
202+
203+
```
182204
## Promises
183205

184206
Use `mutateAsync` instead of `mutate` to get a promise which will resolve on success or throw on an error. This can for example be used to compose side effects.

docs/src/pages/guides/ssr.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ This guide is at-best, a high level overview of how SSR with React Query should
126126
- Dehydrate the client
127127
- Render your app with the client provider and also **using the dehydrated state. This is extremely important! You must render both server and client using the same dehydrated state to ensure hydration on the client produces the exact same markup as the server.**
128128
- Serialize and embed the dehydrated cache to be sent to the client with the HTML
129+
- Clear the React Query caches after the dehydrated state has been sent by calling [`queryClient.clear()`](../reference/QueryClient#queryclientclear)
129130

130131
> SECURITY NOTE: Serializing data with `JSON.stringify` can put you at risk for XSS-vulnerabilities, [this blog post explains why and how to solve it](https://medium.com/node-security/the-most-common-xss-vulnerability-in-react-js-applications-2bdffbcc1fa0)
131132
@@ -155,6 +156,8 @@ async function handleRequest (req, res) {
155156
</body>
156157
</html>
157158
`)
159+
160+
queryClient.clear()
158161
}
159162
```
160163

@@ -196,3 +199,11 @@ A query is considered stale depending on when it was `dataUpdatedAt`. A caveat h
196199
Because `staleTime` defaults to `0`, queries will be refetched in the background on page load by default. You might want to use a higher `staleTime` to avoid this double fetching, especially if you don't cache your markup.
197200

198201
This refetching of stale queries is a perfect match when caching markup in a CDN! You can set the cache time of the page itself decently high to avoid having to re-render pages on the server, but configure the `staleTime` of the queries lower to make sure data is refetched in the background as soon as a user visits the page. Maybe you want to cache the pages for a week, but refetch the data automatically on page load if it's older than a day?
202+
203+
### High memory consumption on server
204+
205+
In case you are creating the `QueryClient` for every request, React Query creates the isolated cache for this client, which is preserved in memory for the `cacheTime` period (which defaults to 5 minutes). That may lead to high memory consumption on server in case of high number of requests during that period.
206+
207+
To clear the cache after it is not needed and to lower memory consumption, you can add a call to [`queryClient.clear()`](../reference/QueryClient#queryclientclear) after the request is handled and dehydrated state has been sent to the client.
208+
209+
Alternatively, you can set a smaller `cacheTime`.

docs/src/pages/reference/useQuery.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ const result = useQuery({
177177
- Optional
178178
- Defaults to `true`
179179
- If set to `false`, structural sharing between query results will be disabled.
180-
- `useErrorBoundary: undefined | boolean | (error: TError) => boolean`
180+
- `useErrorBoundary: undefined | boolean | (error: TError, query: Query) => boolean`
181181
- Defaults to the global query config's `useErrorBoundary` value, which is `undefined`
182182
- Set this to `true` if you want errors to be thrown in the render phase and propagate to the nearest error boundary
183183
- Set this to `false` to disable `suspense`'s default behavior of throwing errors to the error boundary.
184-
- If set to a function, it will be passed the error and should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`)
184+
- If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`)
185185
- `meta: Record<string, unknown>`
186186
- Optional
187187
- If set, stores additional information on the query cache entry that can be used as needed. It will be accessible wherever the `query` is available, and is also part of the `QueryFunctionContext` provided to the `queryFn`.

src/core/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,15 @@ export interface QueryObserverOptions<
183183
* Whether errors should be thrown instead of setting the `error` property.
184184
* If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary.
185185
* If set to `false` and `suspense` is `false`, errors are returned as state.
186-
* If set to a function, it will be passed the error and should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`).
186+
* If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`).
187187
* Defaults to `false`.
188188
*/
189-
useErrorBoundary?: boolean | ((error: TError) => boolean)
189+
useErrorBoundary?:
190+
| boolean
191+
| ((
192+
error: TError,
193+
query: Query<TQueryFnData, TError, TQueryData, TQueryKey>
194+
) => boolean)
190195
/**
191196
* This option can be used to transform or select a part of the data returned by the query function.
192197
*/

src/reactjs/useBaseQuery.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,10 @@ export function useBaseQuery<
127127
result.isError &&
128128
!errorResetBoundary.isReset() &&
129129
!result.isFetching &&
130-
shouldThrowError(defaultedOptions.useErrorBoundary, result.error)
130+
shouldThrowError(defaultedOptions.useErrorBoundary, [
131+
result.error,
132+
observer.getCurrentQuery(),
133+
])
131134
) {
132135
throw result.error
133136
}

src/reactjs/useMutation.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ export function useMutation<
8080
const options = parseMutationArgs(arg1, arg2, arg3)
8181
const queryClient = useQueryClient()
8282

83-
const obsRef = React.useRef<MutationObserver<any, any, any, any>>()
83+
const obsRef = React.useRef<
84+
MutationObserver<TData, TError, TVariables, TContext>
85+
>()
8486

8587
if (!obsRef.current) {
8688
obsRef.current = new MutationObserver(queryClient, options)
@@ -114,10 +116,9 @@ export function useMutation<
114116

115117
if (
116118
currentResult.error &&
117-
shouldThrowError(
118-
!!obsRef.current.options.useErrorBoundary,
119-
currentResult.error
120-
)
119+
shouldThrowError(!!obsRef.current.options.useErrorBoundary, [
120+
currentResult.error,
121+
])
121122
) {
122123
throw currentResult.error
123124
}

src/reactjs/utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
export function shouldThrowError<TError>(
2-
_useErrorBoundary: boolean | ((err: TError) => boolean),
3-
error: TError
1+
export function shouldThrowError<T extends (...args: any[]) => boolean>(
2+
_useErrorBoundary: boolean | T,
3+
params: Parameters<T>
44
): boolean {
55
// Allow useErrorBoundary function to override throwing behavior on a per-error basis
66
if (typeof _useErrorBoundary === 'function') {
7-
return _useErrorBoundary(error)
7+
return _useErrorBoundary(...params)
88
}
99

1010
return _useErrorBoundary

0 commit comments

Comments
 (0)