I want to build a React-component which loads the data asynchronously on componentDidMount
.
This is what the function currently looks like (written in TypeScript
):
async componentDidMount(): Promise<void> {
try {
const { props: { teamId }, state: { } } = this;
const awaitableData = await UrlHelper.getDataAsync("some-fancy-url");
// ... do something with awaitableData
} catch(e) {
console.log("Some error occured");
throw e;
}
}
The render
-function returns the markup wrapped in a ErrorBoundary
component, which has componentDidCatch
implemented.
However, this is never called/triggered when the awaited call is rejected and I end up in the catch
-block.
What am I missing here?
With the new feature in React, developers can test the Error Boundaries by a toggle error button, added to the DevTools. When we click on the toggle error button on the component labeled 'Inner Component', Error boundary is triggered.
Only class components can be error boundaries. In practice, most of the time you'll want to declare an error boundary component once and use it throughout your application. Note that error boundaries only catch errors in the components below them in the tree. An error boundary can't catch an error within itself.
In order to use Error Boundary in Functional Component, I use react-error-boundary. When we run this application, we will get a nice error display form the content of ErrorHandler component. React error boundary catches any error from the components below them in the tree.
An update can be caused by changes to props or state. These methods are called in the following order when a component is being re-rendered: static getDerivedStateFromProps() shouldComponentUpdate() render()
async
function is syntactic sugar for a regular function that returns a promise. An error in async
function results in rejected promise. Even if rejected promise isn't handled anywhere and results in Uncaught (in promise)
error, it is not caught by error boundaries.
As the reference states,
Error boundaries do not catch errors for: <...> Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
A solution is to change component state on error and handle it on next render. render
is the place where error can be re-thrown synchronously.
An example:
state = { error: null };
async componentDidMount() {
try {
await new Promise(resolve => setTimeout(resolve, 2000));
throw new Error('Foo error');
} catch (error) {
this.setState({ error });
}
}
render() {
if (this.state.error) {
throw this.state.error;
}
return (
<p>Foo</p>
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With