@ -17,40 +17,11 @@ function getSubTitleId(isChunkError: boolean, isOffline: boolean): string {
: 'app.error.chunk.description.online' ;
}
/ * *
* Remove failed chunk script / link tags so the bundler runtime can retry loading .
* Utoopack caches failed chunks as rejected promises ; removing the DOM elements
* and clearing its internal cache isn ' t possible via public API , but removing
* the script tags gives us a clean slate on the next retry .
* /
function removeFailedChunkScripts() {
const scripts = document . querySelectorAll (
'script[src][data-failed], link[href][data-failed]' ,
) ;
for ( const el of scripts ) el . remove ( ) ;
}
function renderErrorFallback (
error : Error ,
isOnline : boolean ,
onReload : ( ) = > void ,
onRetry : ( ) = > void ,
) {
function renderErrorFallback ( error : Error , onReload : ( ) = > void ) {
const intl = getIntl ( ) ;
const isOffline = ! isOnl ine;
const isOffline = ! navigator . onLine ;
const isChunkError = isChunkLoadError ( error ) ;
const subTitleId = getSubTitleId ( isChunkError , isOffline ) ;
const retryButton = isChunkError ? (
< Button type = "primary" key = "retry" onClick = { onRetry } >
{ intl . formatMessage ( {
id : 'app.error.retry' ,
defaultMessage : 'Retry' ,
} ) }
< / Button >
) : null ;
return (
< div style = { { padding : 24 } } >
< Card variant = "borderless" >
@ -65,7 +36,7 @@ function renderErrorFallback(
: 'Something went wrong' ,
} ) }
subTitle = { intl . formatMessage ( {
id : subTitleId ,
id : getSubTitleId ( isChunkError , isOffline ) ,
defaultMessage :
isChunkError && isOffline
? 'Your network connection has been lost. Please check your connection and reload.'
@ -74,12 +45,7 @@ function renderErrorFallback(
: 'Sorry, an error occurred on this page. Please reload or go back to the home page.' ,
} ) }
extra = { [
retryButton ,
< Button
type = { isChunkError ? 'default' : 'primary' }
key = "reload"
onClick = { onReload }
>
< Button type = "primary" key = "reload" onClick = { onReload } >
{ intl . formatMessage ( {
id : 'app.error.reload' ,
defaultMessage : 'Reload Page' ,
@ -91,7 +57,7 @@ function renderErrorFallback(
defaultMessage : 'Back Home' ,
} ) }
< / Button > ,
] . filter ( Boolean ) }
] }
/ >
< / Card >
< / div >
@ -112,7 +78,6 @@ export default class ErrorBoundary extends React.Component<
ErrorBoundaryState
> {
state : ErrorBoundaryState = { hasError : false , error : null } ;
private isOnline = typeof navigator !== 'undefined' ? navigator.onLine : true ;
static getDerivedStateFromError ( error : Error ) : Partial < ErrorBoundaryState > {
return { hasError : true , error } ;
@ -120,45 +85,33 @@ export default class ErrorBoundary extends React.Component<
componentDidMount() {
window . addEventListener ( 'online' , this . handleOnline ) ;
window . addEventListener ( 'offline' , this . handleOffline ) ;
}
componentWillUnmount() {
window . removeEventListener ( 'online' , this . handleOnline ) ;
window . removeEventListener ( 'offline' , this . handleOffline ) ;
}
/** Auto-reload when coming back online, but only for chunk load errors. */
handleOnline = ( ) = > {
this . isOnline = true ;
if ( this . state . hasError ) window . location . reload ( ) ;
} ;
handleOffline = ( ) = > {
this . isOnline = false ;
if (
this . state . hasError &&
this . state . error &&
isChunkLoadError ( this . state . error )
) {
window . location . reload ( ) ;
}
} ;
componentDidCatch ( error : Error , info : React.ErrorInfo ) {
console . error ( '[ErrorBoundary]' , error , info . componentStack ) ;
}
/** Soft retry: clear failed scripts, reset state, let React re-render. */
handleRetry = ( ) = > {
removeFailedChunkScripts ( ) ;
this . setState ( { hasError : false , error : null } ) ;
} ;
/** Hard reload: full page refresh. */
handleReload = ( ) = > {
window . location . reload ( ) ;
} ;
render() {
if ( ! this . state . hasError || ! this . state . error ) return this . props . children ;
return renderErrorFallback (
this . state . error ,
this . isOnline ,
this . handleReload ,
this . handleRetry ,
) ;
return renderErrorFallback ( this . state . error , this . handleReload ) ;
}
}