@@ -36,7 +36,15 @@ then be gracefully handled.
36
36
- [ Installation] ( #installation )
37
37
- [ Usage] ( #usage )
38
38
- [ Error Recovery] ( #error-recovery )
39
- - [ fallback prop] ( #fallback-prop )
39
+ - [ API] ( #api )
40
+ - [ ` ErrorBoundary ` props] ( #errorboundary-props )
41
+ - [ ` children ` ] ( #children )
42
+ - [ ` FallbackComponent ` ] ( #fallbackcomponent )
43
+ - [ ` fallbackRender ` ] ( #fallbackrender )
44
+ - [ ` fallback ` ] ( #fallback )
45
+ - [ ` onError ` ] ( #onerror )
46
+ - [ ` onReset ` ] ( #onreset )
47
+ - [ ` resetKeys ` ] ( #resetkeys )
40
48
- [ Issues] ( #issues )
41
49
- [ 🐛 Bugs] ( #-bugs )
42
50
- [ 💡 Feature Requests] ( #-feature-requests )
@@ -62,20 +70,26 @@ its descendants too.
62
70
``` jsx
63
71
import {ErrorBoundary } from ' react-error-boundary'
64
72
65
- function ErrorFallback ({error, componentStack}) {
73
+ function ErrorFallback ({error, componentStack, resetErrorBoundary }) {
66
74
return (
67
75
< div role= " alert" >
68
76
< p> Something went wrong: < / p>
69
77
< pre> {error .message }< / pre>
70
78
< pre> {componentStack}< / pre>
79
+ < button onClick= {resetErrorBoundary}> Try again< / button>
71
80
< / div>
72
81
)
73
82
}
74
83
75
84
const ui = (
76
- < ErrorBoundary FallbackComponent= {ErrorFallback}>
85
+ < ErrorBoundary
86
+ FallbackComponent= {ErrorFallback}
87
+ onReset= {() => {
88
+ // reset the state of your app so the error doesn't happen again
89
+ }}
90
+ >
77
91
< ComponentThatMayError / >
78
- < / ErrorBoundary> ,
92
+ < / ErrorBoundary>
79
93
)
80
94
```
81
95
@@ -115,27 +129,89 @@ const ui = <ComponentWithErrorBoundary />
115
129
116
130
### Error Recovery
117
131
118
- Often you may want to recover from the error. You can do this using the
119
- ` resetErrorBoundary ` prop:
132
+ In the event of an error if you want to recover from that error and allow the
133
+ user to "try again" or continue with their work, you'll need a way to reset the
134
+ ErrorBoundary's internal state. You can do this various ways, but here's the
135
+ most idiomatic approach:
120
136
121
137
``` jsx
122
- function ErrorFallback ({error, resetErrorBoundary}) {
138
+ function ErrorFallback ({error, componentStack, resetErrorBoundary}) {
123
139
return (
124
140
< div role= " alert" >
125
- < div > Oh no < / div >
141
+ < p > Something went wrong : < / p >
126
142
< pre> {error .message }< / pre>
143
+ < pre> {componentStack}< / pre>
127
144
< button onClick= {resetErrorBoundary}> Try again< / button>
128
145
< / div>
129
146
)
130
147
}
148
+
149
+ function Bomb () {
150
+ throw new Error (' 💥 CABOOM 💥' )
151
+ }
152
+
153
+ function App () {
154
+ const [explode , setExplode ] = React .useState (false )
155
+ return (
156
+ < div>
157
+ < button onClick= {() => setExplode (e => ! e)}> toggle explode< / button>
158
+ < ErrorBoundary
159
+ FallbackComponent= {ErrorFallback}
160
+ onReset= {() => setExplode (false )}
161
+ resetKeys= {[explode]}
162
+ >
163
+ {explode ? < Bomb / > : null }
164
+ < / ErrorBoundary>
165
+ < / div>
166
+ )
167
+ }
131
168
```
132
169
133
- However, normally "trying again" like that will just result in the user
134
- experiencing the same error. Typically some other state in your app will need to
135
- be reset as well. The problem is, the ` ErrorFallback ` component won't usually
136
- have access to the state that needs to be reset.
170
+ So, with this setup, you've got a button which when clicked will trigger an
171
+ error. Clicking the button again will trigger a re-render which recovers from
172
+ the error (we no longer render the ` <Bomb /> ` ). We also pass the ` resetKeys `
173
+ prop which is an array of elements for the ` ErrorBoundary ` to check each render
174
+ (if there's currently an error state). If any of those elements change between
175
+ renders, then the ` ErrorBoundary ` will reset the state which will re-render the
176
+ children.
177
+
178
+ We have the ` onReset ` prop so that if the user clicks the "Try again" button we
179
+ have an opportunity to re-initialize our state into a good place before
180
+ attempting to re-render the children.
181
+
182
+ This combination allows us both the opportunity to give the user something
183
+ specific to do to recover from the error, and recover from the error by
184
+ interacting with other areas of the app that might fix things for us. It's hard
185
+ to describe here, but hopefully it makes sense when you apply it to your
186
+ specific scenario.
187
+
188
+ ## API
137
189
138
- So alternatively, you can use the ` fallbackRender ` prop:
190
+ ### ` ErrorBoundary ` props
191
+
192
+ ### ` children `
193
+
194
+ This is what you want rendered when everything's working fine. If there's an
195
+ error that React can handle within the children of the ` ErrorBoundary ` , the
196
+ ` ErrorBoundary ` will catch that and allow you to handle it gracefully.
197
+
198
+ ### ` FallbackComponent `
199
+
200
+ This is a component you want rendered in the event of an error. As props it will
201
+ be passed the ` error ` , ` componentStack ` , and ` resetErrorBoundary ` (which will
202
+ reset the error boundary's state when called, useful for a "try again" button
203
+ when used in combination with the ` onReset ` prop).
204
+
205
+ This is required if no ` fallback ` or ` fallbackRender ` prop is provided.
206
+
207
+ ### ` fallbackRender `
208
+
209
+ This is a render-prop based API that allows you to inline your error fallback UI
210
+ into the component that's using the ` ErrorBoundary ` . This is useful if you need
211
+ access to something that's in the scope of the component you're using.
212
+
213
+ It will be called with an object that has ` error ` , ` componentStack ` , and
214
+ ` resetErrorBoundary ` :
139
215
140
216
``` jsx
141
217
const ui = (
@@ -146,7 +222,10 @@ const ui = (
146
222
< pre> {error .message }< / pre>
147
223
< button
148
224
onClick= {() => {
149
- resetComponentState () // <-- this is why the fallbackRender is useful
225
+ // this next line is why the fallbackRender is useful
226
+ resetComponentState ()
227
+ // though you could accomplish this with a combination
228
+ // of the FallbackCallback and onReset props as well.
150
229
resetErrorBoundary ()
151
230
}}
152
231
>
@@ -165,7 +244,9 @@ around. Unfortunately, the current React Error Boundary API only supports class
165
244
components at the moment, so render props are the best solution we have to this
166
245
problem.
167
246
168
- ### fallback prop
247
+ This is required if no ` FallbackComponent ` or ` fallback ` prop is provided.
248
+
249
+ ### ` fallback `
169
250
170
251
In the spirit of consistency with the ` React.Suspense ` component, we also
171
252
support a simple ` fallback ` prop which you can use for a generic fallback. This
@@ -180,6 +261,28 @@ const ui = (
180
261
)
181
262
```
182
263
264
+ ### ` onError `
265
+
266
+ This will be called when there's been an error that the ` ErrorBoundary ` has
267
+ handled. It will be called with two arguments: ` error ` , ` componentStack ` .
268
+
269
+ ### ` onReset `
270
+
271
+ This will be called immediately before the ` ErrorBoundary ` resets it's internal
272
+ state (which will result in rendering the ` children ` again). You should use this
273
+ to ensure that re-rendering the children will not result in a repeat of the same
274
+ error happening again.
275
+
276
+ ### ` resetKeys `
277
+
278
+ Sometimes an error happens as a result of local state to the component that's
279
+ rendering the error. If this is the case, then you can pass ` resetKeys ` which is
280
+ an array of values. If the ` ErrorBoundary ` is in an error state, then it will
281
+ check these values each render and if they change from one render to the next,
282
+ then it will reset automatically (triggering a re-render of the ` children ` ).
283
+
284
+ See the recovery examples above.
285
+
183
286
## Issues
184
287
185
288
_ Looking to contribute? Look for the [ Good First Issue] [ good-first-issue ]
0 commit comments