Error Handling using Error Boundaries

Last updated on May 28 2022
Nitin Ajmera

Table of Contents

Error Handling using Error Boundaries

In the past, if we get any JavaScript errors inside components, it corrupts the React?s internal state and put React in a broken state on next renders. There are no ways to handle these errors in React components, nor it provides any methods to recover from them. But, React 16 introduces a new concept to handle the errors by using the error boundaries. Now, if any JavaScript error found in a part of the UI, it does not break the whole app.
Error boundaries are React components which catch JavaScript errors anywhere in our app, log those errors, and display a fallback UI. It does not break the whole app component tree and only renders the fallback UI whenever an error occurred in a component. Error boundaries catch errors during rendering in component lifecycle methods, and constructors of the whole tree below them.
Note:
Sometimes, it is not possible to catch Error boundaries in React application. These are:
• Event handlers
• Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
• Server-side rendering
• Errors are thrown in the error boundary itself rather than its children.
For simple React app, we can declare an error boundary once and can use it for the whole application. For a complex application which have multiple components, we can declare multiple error boundaries to recover each part of the entire application.
We can also report the error to an error monitoring service like Rollbar. This monitoring service provides the ability to track how many users are affected by errors, find causes of them, and improve the user experience.

Error boundary in class

A class component can becomes an error boundary if it defines a new lifecycle methods either static getDerivedStateFromError() or componentDidCatch(error, info). We can use static getDerivedStateFromError() to render a fallback UI when an error has been thrown, and can use componentDidCatch() to log error information.
An error boundary can?t catch the error within itself. If the error boundary fails to render the error message, the error will go to the closest error boundary above it. It is similar to the catch {} block in JavaScript.

How to implement error boundaries

Step-1 Create a class which extends React component and passes the props inside it.
Step-2 Now, add componentDidCatch() method which allows you to catch error in the components below them in the tree.
Step-3 Next add render() method, which is responsible for how the component should be rendered. For example, it will display the error message like “Something is wrong.”
Example

1. class ErrorBoundary extends React.Component { 
2. constructor(props) { 
3. super(props); 
4. this.state = { hasError: false }; 
5. } 
6. static getDerivedStateFromError(error) { 
7. // It will update the state so the next render shows the fallback UI. 
8. return { hasError: true }; 
9. } 
10. componentDidCatch(error, info) { 
11. // It will catch error in any component below. We can also log the error to an error reporting service. 
12. logErrorToMyService(error, info); 
13. } 
14. render() { 
15. if (this.state.hasError) { 
16. return ( 
17. <div>Something is wrong.</div>; 
18. ); 
19. } 
20. return this.props.children; 
21. } 
22. }

Step-4 Now, we can use it as a regular component. Add the new component in HTML, which you want to include in the error boundary. In this example, we are adding an error boundary around a MyWidgetCounter component.
1. <ErrorBoundary>
2. <MyWidgetCounter/>
3. </ErrorBoundary>

Where to Place Error Boundaries

An error boundary entirely depends on you. You can use error boundaries on the top-level of the app components or wrap it on the individual components to protect them from breaking the other parts of the app.
Let us see an example.

1. import React from 'react'; 
2. import './App.css' 
3. 
4. class ErrorBoundary extends React.Component { 
5. constructor(props) { 
6. super(props); 
7. this.state = { error: false, errorInfo: null }; 
8. } 
9. 
10. componentDidCatch(error, errorInfo) { 
11. // Catch errors in any components below and re-render with error message 
12. this.setState({ 
13. error: error, 
14. errorInfo: errorInfo 
15. }) 
16. } 
17. 
18. render() { 
19. if (this.state.errorInfo) { 
20. return ( 
21. <div> 
22. <h2>Something went wrong.</h2> 
23. <details style={{ whiteSpace: 'pre-wrap' }}> 
24. {this.state.error && this.state.error.toString()} 
25. <br /> 
26. {this.state.errorInfo.componentStack} 
27. </details> 
28. </div> 
29. ); 
30. } 
31. return this.props.children; 
32. } 
33. } 
34. 
35. class BuggyCounter extends React.Component { 
36. constructor(props) { 
37. super(props); 
38. this.state = { counter: 0 }; 
39. this.handleClick = this.handleClick.bind(this); 
40. } 
41. 
42. handleClick() { 
43. this.setState(({counter}) => ({ 
44. counter: counter + 1 
45. })); 
46. } 
47. 
48. render() { 
49. if (this.state.counter === 3) { 
50. throw new Error('I crashed!'); 
51. } 
52. return <h1 onClick={this.handleClick}>{this.state.counter}</h1>; 
53. } 
54. } 
55. 
56. function App() { 
57. return ( 
58. <div> 
59. <p><b>Example of Error Boundaries</b></p> 
60. <hr /> 
61. <ErrorBoundary> 
62. <p>These two counters are inside the same error boundary.</p> 
63. <BuggyCounter /> 
64. <BuggyCounter /> 
65. </ErrorBoundary> 
66. <hr /> 
67. <p>These two counters are inside of their individual error boundary.</p> 
68. <ErrorBoundary><BuggyCounter /></ErrorBoundary> 
69. <ErrorBoundary><BuggyCounter /></ErrorBoundary> 
70. </div> 
71. ); 
72. } 
73. export default App

In the above code snippet, when we click on the numbers, it increases the counters. The counter is programmed to throw an error when it reaches 3. It simulates a JavaScript error in a component. Here, we used an error boundary in two ways, which are given below.
First, these two counters are inside the same error boundary. If anyone crashes, the error boundary will replace both of them.
1. <ErrorBoundary>
2. <BuggyCounter />
3. <BuggyCounter />
4. </ErrorBoundary>
Second, these two counters are inside of their individual error boundary. So if anyone crashes, the other is not affected.
1. <ErrorBoundary><BuggyCounter /></ErrorBoundary>
2. <ErrorBoundary><BuggyCounter /></ErrorBoundary>
Output:
When we execute the above code, we will get the following output.

reactJs 9
reactJs

When the counter has reached at 3, it gives the following output.

reactJs 10
reactJs

New Behavior for Uncaught error

It is an important implication related to error boundaries. If the error does not catch by any error boundary, it will result in unmounting of the whole React application.

Error Boundary in Event Handler

Error boundaries do not allow catching errors inside event handlers. React does not need any error boundary to recover from errors in the event handler. If there is a need to catch errors in the event handler, you can use JavaScript try-catch statement.
In the below example, you can see how an event handler will handle the errors.

1. class MyComponent extends React.Component { 
2. constructor(props) { 
3. super(props); 
4. this.state = { error: null }; 
5. this.handleClick = this.handleClick.bind(this); 
6. } 
7. 
8. handleClick() { 
9. try { 
10. // Do something which can throw error 
11. } catch (error) { 
12. this.setState({ error }); 
13. } 
14. } 
15. 
16. render() { 
17. if (this.state.error) { 
18. return 
19. <h2>It caught an error.</h2> 
20. } 
21. return <div onClick={this.handleClick}>Click Me</div> 
22. } 
23. }

So, this brings us to the end of blog. This Tecklearn ‘Error Handling using Error Boundaries’ blog helps you with commonly asked questions if you are looking out for a job in React JS and Front-End Development. If you wish to learn React JS and build a career in Front-End Development domain, then check out our interactive, React.js with Redux Training, that comes with 24*7 support to guide you throughout your learning period.

React.js with Redux Training

About the Course

Tecklearn’s React JS Training Course will help you master the fundamentals of React—an important web framework for developing user interfaces—including JSX, props, state, and events. In this course, you will learn how to build simple components & integrate them into more complex design components. After completing this training, you will be able to build the applications using React concepts such as JSX, Redux, Asynchronous Programming using Redux Saga middleware, Fetch data using GraphQL, perform Testing using Jest, successively Deploy applications using Nginx and Docker plus build Mobile applications using React Native. Accelerate your career as a React.js developer by enrolling into this React.js training.

Why Should you take React.js with Redux Training?

• The average salary for “React Developer” ranges from $100,816 per year to $110,711 per year, based on the role (Front End Developer/Full Stack Developer) – Indeed.com
• React Native Supports Cross-platform Development (iOS and Android), and it can reduce the development effort by almost 50% without compromising quality or productivity
• Currently, React JS is being used by major companies like Walmart, Netflix, and HelloSign.

What you will Learn in this Course?

Introduction to Web Development and React.js
• Fundamentals of React
• Building Blocks of Web Application Development
• Single-page and Multi-page Applications
• Different Client-side Technologies
• MVC Architecture
• Introduction to React
• Installation of React
• JSX and its use case
• DOM
• Virtual DOM and its working
• ECMAScript
• Difference between ES5 and ES6
• NPM Modules

Components, JSX & Props
• React Elements
• Render Function
• Components
• Class Component
• Thinking In Components
• What Is JSX
• JSX Expressions
• Creating Your First Component
• Functional Components

React State Management using Redux
• Need of Redux
• Redux Architecture
• Redux Action
• Redux Reducers
• Redux Store
• Principles of Redux
• Pros of Redux
• NPM Packages required to work with Redux
• More about react-redux package
React & Redux
• The React Redux Node Package
• Provider Component
• Connecting React Components with Redux Store
• Reducer Composition
• Normalization: Points to Keep in Mind When Designing a Redux Store
• Redux Middleware

React Hooks
• Caveat of JavaScript classes.
• Functional components and React hooks
• What are React hooks?
• Basic hooks
• useState() hook
• How to write useState() hook when state variable is an array of objects
• useEffect() hook
• Fetch API data using useEffect() hook
• useContext() hook
• Rules to write React hooks
• Additional hooks
• Custom hooks

Fetch Data using GraphQL
• What is GraphQL?
• Cons of Rest API
• Pros of GraphQL
• Frontend backend communication using GraphQL
• Type system
• GraphQL datatypes
• Modifiers
• Schemas
• GraphiQL tool
• Express framework
• NPM libraries to build server side of GraphQL
• Build a GraphQL API
• Apollo client
• NPM libraries to build client side of GraphQL
• How to setup Apollo client

React Application Testing and Deployment
• Define Jest
• Setup Testing environment
• Add Snapshot testing
• Integrate Test Reducers
• Create Test Components
• Push Application on Git
• Create Docker for React Application

Introduction to React Native
• What is React Native
• Use of JSX elements With React Native
• The anatomy of a React Native application
• React Native installation and setup
• Running the app on Android Simulator and Android Device
• Working with Styles and Layout
• Connecting React Native to Redux

React with Redux Projects

Got a question for us? Please mention it in the comments section and we will get back to you.

 

0 responses on "Error Handling using Error Boundaries"

Leave a Message

Your email address will not be published. Required fields are marked *