Skip to content

Commit 1c8196a

Browse files
Merge branch 'tannerlinsley:master' into master
2 parents 9c9f3cf + 058977a commit 1c8196a

File tree

17 files changed

+475
-75
lines changed

17 files changed

+475
-75
lines changed

docs/src/components/markdown.module.css

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,19 @@
6161
@apply text-base;
6262
}
6363

64-
.markdown > p > a,
65-
.markdown > ul > li > a,
66-
.markdown > ol > li > a,
67-
.markdown > blockquote > p > a,
68-
.markdown > table > tbody > tr > td > a {
64+
.markdown p > a,
65+
.markdown ul > li > a,
66+
.markdown ol > li > a,
67+
.markdown blockquote > p > a,
68+
.markdown table > tbody > tr > td > a {
6969
@apply text-blue-600 font-semibold transition-colors duration-150 ease-out;
7070
}
7171

72-
.markdown > p > a:hover,
73-
.markdown > ul > li > a:hover,
74-
.markdown > ol > li > a:hover,
75-
.markdown > blockquote > p > a:hover,
76-
.markdown > table > tbody > tr > td > a:hover {
72+
.markdown p > a:hover,
73+
.markdown ul > li > a:hover,
74+
.markdown ol > li > a:hover,
75+
.markdown blockquote > p > a:hover,
76+
.markdown table > tbody > tr > td > a:hover {
7777
@apply text-blue-800 transition-colors duration-150 ease-out;
7878
}
7979

docs/src/images/emblem-light.svg

Lines changed: 5 additions & 5 deletions
Loading

docs/src/images/logo.svg

Lines changed: 14 additions & 14 deletions
Loading

docs/src/images/logos/walmart.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/pages/community/tkdodos-blog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,7 @@ React Query maintainer [TkDodo](https://twitter.com/tkdodo) has a series of blog
4545
## [#10: React Query as a State Manager](https://tkdodo.eu/blog/react-query-as-a-state-manager)
4646

4747
> React Query doesn't fetch any data for you - it's a data synchronization tool that excels when used for server state. This article has everything you need to know to make React Query your single source of truth state manager for your async state. You'll learn how to let React Query do it's magic and why customizing `staleTime` might be all you need. [Read more...](https://tkdodo.eu/blog/react-query-as-a-state-manager)
48+
49+
## [#11: React Query Error Handling](https://tkdodo.eu/blog/react-query-error-handling)
50+
51+
> Handling errors is an integral part of working with asynchronous data, especially data fetching. We have to face it: Not all requests will be successful, and not all Promises will be fulfilled. This blog post describes various ways of coping with errors in React Query, such as the error property, using Error Boundaries or onError callbacks, so that you can prepare your application for the cases when "Something went wrong". [Read more...](https://tkdodo.eu/blog/react-query-error-handling)

docs/src/pages/guides/testing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ await waitFor(() => {
121121
return result.current.isSuccess;
122122
});
123123
124-
expect(result.current).toEqual({answer: 42});
124+
expect(result.current.data).toEqual({answer: 42});
125125
```
126126

127127
Here we are making use of `waitFor` and waiting until our the query status indicates that the request has succeeded. This way we know that our hook has finished and should have the correct data.

docs/src/pages/reference/useMutation.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ mutate(variables, {
6666
- This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the next attempt in milliseconds.
6767
- A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.
6868
- A function like `attempt => attempt * 1000` applies linear backoff.
69-
- `useErrorBoundary`
70-
- Defaults to the global query config's `useErrorBoundary` value, which is `false`
71-
- Set this to true if you want mutation errors to be thrown in the render phase and propagate to the nearest error boundary
69+
- `useErrorBoundary: undefined | boolean | (error: TError) => boolean`
70+
- Defaults to the global query config's `useErrorBoundary` value, which is `undefined`
71+
- Set this to `true` if you want mutation errors to be thrown in the render phase and propagate to the nearest error boundary
72+
- Set this to `false` to disable the behaviour of throwing errors to the error boundary.
73+
- 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`)
7274

7375
**Returns**
7476

docs/src/pages/reference/useQuery.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,11 @@ const result = useQuery({
170170
- Optional
171171
- Defaults to `true`
172172
- If set to `false`, structural sharing between query results will be disabled.
173-
- `useErrorBoundary: boolean`
174-
- Defaults to the global query config's `useErrorBoundary` value, which is false
175-
- Set this to true if you want errors to be thrown in the render phase and propagated to the nearest error boundary
173+
- `useErrorBoundary: undefined | boolean | (error: TError) => boolean`
174+
- Defaults to the global query config's `useErrorBoundary` value, which is `undefined`
175+
- Set this to `true` if you want errors to be thrown in the render phase and propagate to the nearest error boundary
176+
- Set this to `false` to disable `suspense`'s default behaviour of throwing errors to the error boundary.
177+
- 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`)
176178
177179
**Returns**
178180

src/core/mutationObserver.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { QueryClient } from './queryClient'
44
import { Subscribable } from './subscribable'
55
import type {
66
MutateOptions,
7+
MutationObserverBaseResult,
78
MutationObserverResult,
89
MutationObserverOptions,
910
} from './types'
@@ -129,7 +130,12 @@ export class MutationObserver<
129130
? this.currentMutation.state
130131
: getDefaultState<TData, TError, TVariables, TContext>()
131132

132-
this.currentResult = {
133+
const result: MutationObserverBaseResult<
134+
TData,
135+
TError,
136+
TVariables,
137+
TContext
138+
> = {
133139
...state,
134140
isLoading: state.status === 'loading',
135141
isSuccess: state.status === 'success',
@@ -138,6 +144,13 @@ export class MutationObserver<
138144
mutate: this.mutate,
139145
reset: this.reset,
140146
}
147+
148+
this.currentResult = result as MutationObserverResult<
149+
TData,
150+
TError,
151+
TVariables,
152+
TContext
153+
>
141154
}
142155

143156
private notify(options: NotifyOptions) {

src/core/types.ts

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,12 @@ export interface QueryObserverOptions<
163163
onSettled?: (data: TData | undefined, error: TError | null) => void
164164
/**
165165
* Whether errors should be thrown instead of setting the `error` property.
166+
* If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary.
167+
* If set to `false` and `suspense` is `false`, errors are returned as state.
168+
* 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`).
166169
* Defaults to `false`.
167170
*/
168-
useErrorBoundary?: boolean
171+
useErrorBoundary?: boolean | ((error: TError) => boolean)
169172
/**
170173
* This option can be used to transform or select a part of the data returned by the query function.
171174
*/
@@ -527,7 +530,7 @@ export interface MutationObserverOptions<
527530
TVariables = void,
528531
TContext = unknown
529532
> extends MutationOptions<TData, TError, TVariables, TContext> {
530-
useErrorBoundary?: boolean
533+
useErrorBoundary?: boolean | ((error: TError) => boolean)
531534
}
532535

533536
export interface MutateOptions<
@@ -564,7 +567,7 @@ export type MutateFunction<
564567
options?: MutateOptions<TData, TError, TVariables, TContext>
565568
) => Promise<TData>
566569

567-
export interface MutationObserverResult<
570+
export interface MutationObserverBaseResult<
568571
TData = unknown,
569572
TError = unknown,
570573
TVariables = void,
@@ -578,6 +581,77 @@ export interface MutationObserverResult<
578581
reset: () => void
579582
}
580583

584+
export interface MutationObserverIdleResult<
585+
TData = unknown,
586+
TError = unknown,
587+
TVariables = void,
588+
TContext = unknown
589+
> extends MutationObserverBaseResult<TData, TError, TVariables, TContext> {
590+
data: undefined
591+
error: null
592+
isError: false
593+
isIdle: true
594+
isLoading: false
595+
isSuccess: false
596+
status: 'idle'
597+
}
598+
599+
export interface MutationObserverLoadingResult<
600+
TData = unknown,
601+
TError = unknown,
602+
TVariables = void,
603+
TContext = unknown
604+
> extends MutationObserverBaseResult<TData, TError, TVariables, TContext> {
605+
data: undefined
606+
error: null
607+
isError: false
608+
isIdle: false
609+
isLoading: true
610+
isSuccess: false
611+
status: 'loading'
612+
}
613+
614+
export interface MutationObserverErrorResult<
615+
TData = unknown,
616+
TError = unknown,
617+
TVariables = void,
618+
TContext = unknown
619+
> extends MutationObserverBaseResult<TData, TError, TVariables, TContext> {
620+
data: undefined
621+
error: TError
622+
isError: true
623+
isIdle: false
624+
isLoading: false
625+
isSuccess: false
626+
status: 'error'
627+
}
628+
629+
export interface MutationObserverSuccessResult<
630+
TData = unknown,
631+
TError = unknown,
632+
TVariables = void,
633+
TContext = unknown
634+
> extends MutationObserverBaseResult<TData, TError, TVariables, TContext> {
635+
data: TData
636+
error: null
637+
isError: false
638+
isIdle: false
639+
isLoading: false
640+
isSuccess: true
641+
status: 'success'
642+
}
643+
644+
export type MutationObserverResult<
645+
TData = unknown,
646+
TError = unknown,
647+
TVariables = void,
648+
TContext = unknown
649+
> =
650+
| MutationObserverIdleResult<TData, TError, TVariables, TContext>
651+
| MutationObserverLoadingResult<TData, TError, TVariables, TContext>
652+
| MutationObserverErrorResult<TData, TError, TVariables, TContext>
653+
| MutationObserverSuccessResult<TData, TError, TVariables, TContext>
654+
581655
export interface DefaultOptions<TError = unknown> {
582656
queries?: QueryObserverOptions<unknown, TError>
583657
mutations?: MutationObserverOptions<unknown, TError, unknown, unknown>

0 commit comments

Comments
 (0)