Error Boundaries in React 18

Max Headway
4 min readMar 16, 2023

--

React is a popular JavaScript library for building user interfaces. TypeScript is a language that extends JavaScript by adding type annotations and other features. TypeScript can be used with React to improve code quality and maintainability. One important aspect of building robust React applications is error handling. In this article, we will discuss how to use ErrorBoundary in React with TypeScript.

ErrorBoundary is a React component that catches JavaScript errors anywhere in its child component tree, logs those errors, and displays a fallback UI instead of crashing the entire application. ErrorBoundary is a powerful tool for improving the user experience of your React application.

To use ErrorBoundary in React with TypeScript, we need to follow a few steps.

Step 1: Install the required packages

The first step is to install the required packages. We need to install the following packages:

  • @types/react and @types/react-dom for TypeScript definitions of React and ReactDOM.
  • react-error-boundary for ErrorBoundary.

We can install these packages using the following command:

npm install @types/react @types/react-dom react-error-boundary

Step 2: Create an ErrorBoundary component

Next, we need to create an ErrorBoundary component. Here’s an example of an ErrorBoundary component in TypeScript:

import React from 'react';
import { FallbackProps } from 'react-error-boundary';

interface ErrorBoundaryProps {
children: React.ReactNode;
fallbackComponent: React.ComponentType<FallbackProps>;
}

interface ErrorBoundaryState {
hasError: boolean;
}

class ErrorBoundary extends React.Component<
ErrorBoundaryProps,
ErrorBoundaryState
> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(): ErrorBoundaryState {
return { hasError: true };
}

render(): React.ReactNode {
const { hasError } = this.state;
const { children, fallbackComponent: FallbackComponent } = this.props;

if (hasError) {
return <FallbackComponent />;
}

return children;
}
}

export default ErrorBoundary;

Here, we have created a class component called ErrorBoundary that extends React.Component. We have defined two interfaces, ErrorBoundaryProps and ErrorBoundaryState. ErrorBoundaryProps defines the props that this component expects, while ErrorBoundaryState defines the state of the component.

We have defined the constructor and set the initial state of the component to hasError: false. We have also defined a static method called getDerivedStateFromError() that returns an updated state when an error occurs.

Finally, we have implemented the render() method. If an error has occurred, we return the fallback component passed in through the props. Otherwise, we return the children.

Step 3: Use the ErrorBoundary component

Now that we have created an ErrorBoundary component, we can use it in our application. Here’s an example:

import React from 'react';
import ErrorBoundary from './ErrorBoundary';

function MyComponent(): JSX.Element {
const throwError = () => {
throw new Error('Something went wrong');
};

return (
<ErrorBoundary fallbackComponent={ErrorFallback}>
<button onClick={throwError}>Throw error</button>
</ErrorBoundary>
);
}

function ErrorFallback(): JSX.Element {
return <div>Something went wrong</div>;
}

export default MyComponent;

In this example, we have created a simple component called MyComponent. We have defined a function called throwError that throws an error when a button is clicked. We have also defined a fallback component called ErrorFallback that is displayed when an error occurs

import React from 'react';
import { FallbackProps } from 'react-error-boundary';

interface ErrorBoundaryProps {
children: React.ReactNode;
fallbackComponent: React.ComponentType<FallbackProps>;
}

interface ErrorBoundaryState {
hasError: boolean;
}

class ErrorBoundary extends React.Component<
ErrorBoundaryProps,
ErrorBoundaryState
> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(): ErrorBoundaryState {
return { hasError: true };
}

render(): React.ReactNode {
const { hasError } = this.state;
const { children, fallbackComponent: FallbackComponent } = this.props;

if (hasError) {
return <FallbackComponent />;
}

return children;
}
}

export default ErrorBoundary;

Here, we have created a class component called ErrorBoundary that extends React.Component. We have defined two interfaces, ErrorBoundaryProps and ErrorBoundaryState. ErrorBoundaryProps defines the props that this component expects, while ErrorBoundaryState defines the state of the component.

Using the ErrorBoundary Component

Once we have created our ErrorBoundary component, we can use it in our React application. We simply need to wrap the components that we want to catch errors from inside the ErrorBoundary component.

Here’s an example of how to use the ErrorBoundary component in a TypeScript React application:

import React from "react";
import ErrorBoundary from "./ErrorBoundary";
import MyComponent from "./MyComponent";

function App() {
return (
<div className="App">
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
</div>
);
}

export default App;

In the example above, we have wrapped the MyComponent component with the ErrorBoundary component. If an error occurs inside MyComponent, it will be caught by the ErrorBoundary component and we can display a fallback UI to the user.

Testing ErrorBoundaries

Testing ErrorBoundaries can be tricky as Jest does not provide a native way to test them. However, we can use third-party libraries like react-test-renderer to test the ErrorBoundary component.

Here’s an example of how to test the ErrorBoundary component using react-test-renderer:

import React from "react";
import { render } from "react-test-renderer";
import ErrorBoundary from "./ErrorBoundary";

describe("ErrorBoundary", () => {
it("should render the fallback UI when an error occurs", () => {
const error = new Error("Oops! Something went wrong.");
const component = render(
<ErrorBoundary>
<ChildComponent />
</ErrorBoundary>
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

function ChildComponent() {
throw new Error("Oops! Something went wrong.");
}

In the example above, we have created a test for the ErrorBoundary component. We have intentionally thrown an error inside the ChildComponent component to test if the ErrorBoundary component catches the error and displays the fallback UI.

Conclusion

In this article, we have learned how to use ErrorBoundary components in a TypeScript React application. ErrorBoundaries allow us to catch errors that occur in our React components and display a fallback UI to the user. By using ErrorBoundaries, we can ensure that our React application does not crash when an error occurs and provide a better user experience.

When developing a TypeScript React application, it is important to use ErrorBoundaries to catch errors and handle them gracefully. By doing so, we can ensure that our application is stable, reliable, and provides a great user experience.

--

--

Max Headway

Programming nerd just trying to share what I learn with the world.