问题
I am learning React and am unable to get an Error Boundary catching a network connection error thrown by an axios http request in a child component when the API server is unavailable.
I can see that the error is logged in the catch handler of the child component, however the throw statement is not caught by the ErrorBoundary component.
Any ideas how to get the Error Boundary catching an error thrown from componentDidMount lifecycle method?
Parent - App.tsx
export class App extends React.Component<AppProps, {}> {
public render(): JSX.Element {
return (
<div>
<ErrorBoundary>
<AppBar color="primary" position="static">
<Toolbar>
<TypoGraphy variant="h6" color="inherit">
Course App
</TypoGraphy>
<NavBar />
</Toolbar>
</AppBar>
<CourseList />
</ErrorBoundary>
</div>
);
}
}
Child - CourseList.tsx
componentDidMount(): void {
console.log('CourseList::componentDidMount');
const dataSource: RestDataCourse = new RestDataCourse();
dataSource
.getCourses()
.then(courseList => {
this.setState({ courses: courseList });
})
.catch(error => {
console.error(`Error retrieving courses => ${JSON.stringify(error)}`);
throw error;
});
}
ErrorBoundary
import * as React from 'react';
interface ErrorBoundaryProps {
hasError: boolean;
error: Error;
info: React.ErrorInfo;
}
export default class ErrorBoundary extends React.Component<
{},
ErrorBoundaryProps
> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false, error: undefined, info: undefined };
}
componentDidCatch(error: any, info: any): void {
console.log('ErrorBoundary has encountered an error');
this.setState({ hasError: true, error: error, info: info });
}
render(): {} {
if (this.state.hasError) {
return (
<div id="errorModal" className="modal">
<div className="modal-content">
<span className="close">×</span>
<h2>Application Crash</h2>
<p>Error encountered in application.</p>
{this.state.error}
</div>
</div>
);
}
// Render children if no error
return this.props.children;
}
}
回答1:
Error boundaries are designed to catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
If you want to catch unhandled promise errors globally (instead of handling it directly in component), you can use window.onunhandledrejection.
window.onunhandledrejection = function(e) {
console.log(e.reason);
}
but it's not supported in all browsers by default.
Little hacky solution would be to call this.setState(() => { throw err; });
in catch
of your promise.
来源:https://stackoverflow.com/questions/58267208/error-thrown-from-child-component-in-componentdidmount-lifecycle-method-is-not-c