@@ -46,6 +46,19 @@ navigationInit()
46
46
const reloadStorageKey = `gatsby-reload-compilation-hash-match`
47
47
48
48
apiRunnerAsync ( `onClientEntry` ) . then ( ( ) => {
49
+ // Set up React 19 error handling
50
+ const handleUncaughtError = ( error , errorInfo ) => {
51
+ // Report uncaught errors to any error tracking service
52
+ console . error ( `Uncaught error:` , error , errorInfo )
53
+ apiRunner ( `onUncaughtError` , { error, errorInfo } )
54
+ }
55
+
56
+ const handleCaughtError = ( error , errorInfo ) => {
57
+ // Report caught errors to any error tracking service
58
+ console . error ( `Caught error:` , error , errorInfo )
59
+ apiRunner ( `onCaughtError` , { error, errorInfo } )
60
+ }
61
+
49
62
// Let plugins register a service worker. The plugin just needs
50
63
// to return true.
51
64
if ( apiRunner ( `registerServiceWorker` ) . filter ( Boolean ) . length > 0 ) {
@@ -277,16 +290,23 @@ apiRunnerAsync(`onClientEntry`).then(() => {
277
290
278
291
// Client only pages have any empty body so we just do a normal
279
292
// render to avoid React complaining about hydration mis-matches.
280
- let defaultRenderer = render
293
+ let defaultRenderer = ( Component , el ) =>
294
+ render ( Component , el , {
295
+ onUncaughtError : handleUncaughtError ,
296
+ onCaughtError : handleCaughtError ,
297
+ } )
298
+
281
299
if ( focusEl && focusEl . children . length ) {
282
- defaultRenderer = hydrate
300
+ defaultRenderer = ( Component , el ) =>
301
+ hydrate ( Component , el , {
302
+ onUncaughtError : handleUncaughtError ,
303
+ onCaughtError : handleCaughtError ,
304
+ } )
283
305
}
284
306
285
- const renderer = apiRunner (
286
- `replaceHydrateFunction` ,
287
- undefined ,
307
+ const renderer =
308
+ apiRunner ( `replaceHydrateFunction` , undefined , defaultRenderer ) [ 0 ] ||
288
309
defaultRenderer
289
- ) [ 0 ]
290
310
291
311
function runRender ( ) {
292
312
const rootElement =
0 commit comments