Skip to content

Commit bfca612

Browse files
authored
reset error state when calling useMutation's reset (TanStack#130)
* reset error state when executing useMutation's reset * update README and CHANGELOG
1 parent 9f3b2e9 commit bfca612

File tree

5 files changed

+80
-9
lines changed

5 files changed

+80
-9
lines changed

.size-snapshot.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"dist/index.js": {
3-
"bundled": 31764,
4-
"minified": 16087,
5-
"gzipped": 4618
3+
"bundled": 31777,
4+
"minified": 16088,
5+
"gzipped": 4619
66
},
77
"dist/index.es.js": {
8-
"bundled": 31223,
9-
"minified": 15604,
10-
"gzipped": 4516,
8+
"bundled": 31236,
9+
"minified": 15605,
10+
"gzipped": 4517,
1111
"treeshaked": {
1212
"rollup": {
1313
"code": 3329,

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
- Added the `useMutation.throwOnError` and corresponding `queryConfig.throwOnError` option to configure whether the `mutate` function rethrows errors encountered in the mutation function
1414
- Added the `useMutation.useErrorBoundary` and corresponding `queryConfig.useErrorBoundary` option to configure whether mutation errors should be thrown during the render function and propagated to the nearest error boundary. This option will default to the same value as `queryConfig.suspense` if not defined otherwise
15+
- Added a new `reset` function for `useMutation` which will revert the hook's state back to the initial `null` state
1516

1617
## 0.3.27
1718

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,37 @@ mutate(
947947
const { data, isLoading, error } = useQuery(['todo', { id: 5 }], fetchTodoByID)
948948
```
949949
950+
### Resetting Mutation State
951+
952+
It's sometimes the case that you need to clear the `error` or `data` of a mutation request. To do this, you can use the `reset` function to handle this:
953+
954+
```js
955+
const CreateTodo = () => {
956+
const [title, setTitle] = useState('')
957+
const [mutate, { error, mutate }] = useMutation(createTodo)
958+
959+
const onCreateTodo = async e => {
960+
e.preventDefault()
961+
await mutate({ title })
962+
}
963+
964+
return (
965+
<form onSubmit={onCreateTodo}>
966+
{error &&
967+
<h5 onClick={() => reset()}>{error}</h5>
968+
}
969+
<input
970+
type="text"
971+
value={title}
972+
onChange={e => setTitle(e.target.value)}
973+
/>
974+
<br />
975+
<button type="submit">Create Todo</button>
976+
</form>
977+
)
978+
}
979+
```
980+
950981
## Manually or Optimistically Setting Query Data
951982
952983
In rare circumstances, you may want to manually update a query's response before it has been refetched. To do this, you can use the exported `setQueryData` function:
@@ -1385,7 +1416,7 @@ const {
13851416
## `useMutation`
13861417
13871418
```js
1388-
const [mutate, { data, isLoading, error }] = useMutation(mutationFn, {
1419+
const [mutate, { data, isLoading, error, reset }] = useMutation(mutationFn, {
13891420
refetchQueries,
13901421
refetchQueriesOnFailure,
13911422
useErrorBoundary,
@@ -1433,6 +1464,8 @@ const promise = mutate(variables, { updateQuery, waitForRefetchQueries })
14331464
- The last successfully resolved data for the query.
14341465
- `error: null | Error`
14351466
- The error object for the query, if an error was thrown.
1467+
- `reset: Function() => void`
1468+
- Sets the mutation's `data` and `error` fields to `null`.
14361469
- `isLoading: Boolean`
14371470
- Will be `true` if the query is both fetching and does not have any cached data.
14381471
- `promise: Promise`

src/__tests__/useMutation-test.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
waitForElement,
66
} from '@testing-library/react'
77
import * as React from 'react'
8-
import { act } from 'react-dom/test-utils'
98

109
import { useMutation } from '../index'
1110

@@ -43,4 +42,39 @@ describe('useMutation', () => {
4342

4443
expect(getByTestId('title').textContent).toBe('')
4544
})
45+
46+
it('should be able to reset `error`', async () => {
47+
function Page() {
48+
const [mutate, mutationResult] = useMutation(
49+
() => Promise.reject(new Error('something went wrong')),
50+
{
51+
throwOnError: false
52+
}
53+
)
54+
55+
return (
56+
<div>
57+
{mutationResult.error &&
58+
<h1 data-testid="error">{mutationResult.error.message}</h1>
59+
}
60+
<button onClick={mutationResult.reset}>reset</button>
61+
<button onClick={mutate}>mutate</button>
62+
</div>
63+
)
64+
}
65+
66+
const { getByTestId, getByText, queryByTestId } = render(<Page />)
67+
68+
expect(queryByTestId('error')).toBeNull()
69+
70+
fireEvent.click(getByText('mutate'))
71+
72+
await waitForElement(() => getByTestId('error'))
73+
74+
expect(getByTestId('error').textContent).toBe('something went wrong')
75+
76+
fireEvent.click(getByText('reset'))
77+
78+
expect(queryByTestId('error')).toBeNull()
79+
})
4680
})

src/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,10 @@ export function useMutation(
697697
[refetchQueries, refetchQueriesOnFailure, throwOnError]
698698
)
699699

700-
const reset = React.useCallback(() => setData(null), [])
700+
const reset = React.useCallback(() => {
701+
setData(null)
702+
setError(null)
703+
}, [])
701704

702705
React.useEffect(() => {
703706
if (useErrorBoundary && error) {

0 commit comments

Comments
 (0)