Skip to content

Commit dd6022e

Browse files
authored
feat(onResetKeysChange): handle when the reset keys change (#52)
1 parent c30eda2 commit dd6022e

File tree

4 files changed

+22
-8
lines changed

4 files changed

+22
-8
lines changed

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ then be gracefully handled.
4545
- [`onError`](#onerror)
4646
- [`onReset`](#onreset)
4747
- [`resetKeys`](#resetkeys)
48+
- [`onResetKeysChange`](#onresetkeyschange)
4849
- [Issues](#issues)
4950
- [🐛 Bugs](#-bugs)
5051
- [💡 Feature Requests](#-feature-requests)
@@ -273,10 +274,10 @@ state (which will result in rendering the `children` again). You should use this
273274
to ensure that re-rendering the children will not result in a repeat of the same
274275
error happening again.
275276

276-
`onReset` will be called with whatever `resetErrorBoundary` is called with. In
277-
the case of `resetKeys`, it's called with the `prevResetKeys` and the
278-
`resetKeys`. This can help you differentiate between a reset that occurred due
279-
to a "try again" button click and one trigged by a `resetKeys` change.
277+
`onReset` will be called with whatever `resetErrorBoundary` is called with.
278+
279+
**Important**: `onReset` will _not_ be called when reset happens from a change
280+
in `resetKeys`. Use `onResetKeysChange` for that.
280281

281282
### `resetKeys`
282283

@@ -288,6 +289,11 @@ then it will reset automatically (triggering a re-render of the `children`).
288289

289290
See the recovery examples above.
290291

292+
### `onResetKeysChange`
293+
294+
This is called when the `resetKeys` are changed (triggering a reset of the
295+
`ErrorBoundary`). It's called with the `prevResetKeys` and the `resetKeys`.
296+
291297
## Issues
292298

293299
_Looking to contribute? Look for the [Good First Issue][good-first-issue]

index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,23 @@ export interface FallbackProps {
77
}
88

99
export interface ErrorBoundaryPropsWithComponent {
10+
onResetKeysChange?: (prevResetKeys: Array<any>, resetKeys: Array<any>) => void
1011
onReset?: () => void
1112
onError?: (error: Error, componentStack: string) => void
1213
resetKeys?: Array<any>
1314
FallbackComponent: React.ComponentType<FallbackProps>
1415
}
1516

1617
export interface ErrorBoundaryPropsWithRender {
18+
onResetKeysChange?: (prevResetKeys: Array<any>, resetKeys: Array<any>) => void
1719
onReset?: () => void
1820
onError?: (error: Error, componentStack: string) => void
1921
resetKeys?: Array<any>
2022
fallbackRender: (props: FallbackProps) => React.ReactElement<any, any> | null
2123
}
2224

2325
export interface ErrorBoundaryPropsWithFallback {
26+
onResetKeysChange?: (prevResetKeys: Array<any>, resetKeys: Array<any>) => void
2427
onReset?: () => void
2528
onError?: (error: Error, componentStack: string) => void
2629
resetKeys?: Array<any>

src/__tests__/index.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ test('supports automatic reset of error boundary when resetKeys change', () => {
255255
const handleReset = jest.fn()
256256
const TRY_AGAIN_ARG1 = 'TRY_AGAIN_ARG1'
257257
const TRY_AGAIN_ARG2 = 'TRY_AGAIN_ARG2'
258+
const handleResetKeysChange = jest.fn()
258259
function App() {
259260
const [explode, setExplode] = React.useState(false)
260261
return (
@@ -276,6 +277,7 @@ test('supports automatic reset of error boundary when resetKeys change', () => {
276277
setExplode(false)
277278
handleReset(...args)
278279
}}
280+
onResetKeysChange={handleResetKeysChange}
279281
resetKeys={[explode]}
280282
>
281283
{explode ? <Bomb /> : null}
@@ -298,6 +300,7 @@ test('supports automatic reset of error boundary when resetKeys change', () => {
298300
expect(handleReset).toHaveBeenCalledWith(TRY_AGAIN_ARG1, TRY_AGAIN_ARG2)
299301
expect(handleReset).toHaveBeenCalledTimes(1)
300302
handleReset.mockClear()
303+
expect(handleResetKeysChange).not.toHaveBeenCalled()
301304

302305
// blow it up again
303306
userEvent.click(screen.getByText('toggle explode'))
@@ -307,9 +310,10 @@ test('supports automatic reset of error boundary when resetKeys change', () => {
307310

308311
// recover via resetKeys change
309312
userEvent.click(screen.getByText('toggle explode'))
310-
expect(handleReset).toHaveBeenCalledWith([true], [false])
311-
expect(handleReset).toHaveBeenCalledTimes(1)
312-
handleReset.mockClear()
313+
expect(handleResetKeysChange).toHaveBeenCalledWith([true], [false])
314+
expect(handleResetKeysChange).toHaveBeenCalledTimes(1)
315+
handleResetKeysChange.mockClear()
316+
expect(handleReset).not.toHaveBeenCalled()
313317
expect(screen.queryByRole('alert')).not.toBeInTheDocument()
314318
expect(console.error).not.toHaveBeenCalled()
315319
})

src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ class ErrorBoundary extends React.Component {
2020
const {error} = this.state
2121
const {resetKeys} = this.props
2222
if (error !== null && changedArray(prevProps.resetKeys, resetKeys)) {
23-
this.resetErrorBoundary(prevProps.resetKeys, resetKeys)
23+
this.props.onResetKeysChange?.(prevProps.resetKeys, resetKeys)
24+
this.setState(initialState)
2425
}
2526
}
2627

0 commit comments

Comments
 (0)