How to implement Error Boundaries In React Native

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the crashed component tree that crashed.

Why Should You Use Them? ūü§Ē

Official docs: https://reactjs.org/docs/error-boundaries.html#new-behavior-for-uncaught-errors

Unmounting the whole React component tree means that if we don’t catch errors, the user will see an empty white screen. Most of the time, without having any feedback so it will hamper the user experience. So this problem should be fixed with the help of Error Boundaries.

Implementation:

Error Boundaries are class components. With the help of Error Boundaries, we can catch types of error, error info and display fallback UI.

export default class AppContainer extends Component {

  render() {

    return (

      <>

        <ErrorBoundries>

         {/* Rest of code */}

        </ErrorBoundries>

      </>

    );

  }

 }

Error Boundaries catch errors in their child components, during the rendering phase. And if any error is found it will give error details and fallback UI with help of the below lifecycle methods.

To achieve Error Boundaries, we need to add two lifecycle methods in the component.

getDerivedStateFromError(error):

This static lifecycle method is invoked when an error occurs, and that error can originate from any child component of the error boundary.

We can update the state of the component by returning a state like hasError:true, this will re-render the component and display fallback UI with help of conditional rendering.

componentDidCatch(error, errorInfo) :

This lifecycle method is optional. It is invoked after an error has been thrown by the descendant component. offers additional parameters, the error is for getting the type of error and errorInfo is an object with componentStack key which contains information where the error originally occurred.

For example, we have a sample counter app. If the value of the counter is negative, then we are throwing a JavaScript error. Let see how error boundaries have tracked error. Also, we are showing error info and error track details with the help of componentDidCatch (as mentioned above).

1. We have added components as a child component in error boundaries

AppContainer.js

export default class AppContainer extends Component {

  render() {

    return (

      <>

        <Text>Counter App</Text>

        <ErrorBoundries>

             <CounterApp />

        </ErrorBoundries>

      </>

    );

  }

 }

2. If the counter value is negative then we are throwing javascript error as below

if (state < 0) {

   throw new Error('Value should be Postitive');

  }

CounterApp.js

 import React, {useState} from 'react';

 import {View, Text, Pressable} from 'react-native';

 export default function CounterApp() {

  const [state, setState] = useState(0);

  const counterAdd = () => {

    setState(prevState => prevState + 1);

  };

  const counterRemove = () => {

    setState(prevState => prevState - 1);

  };

  if (state < 0) {

    throw new Error('Value should be Postitive');

  }

  return (

    <>

      <View

        style={{

          flex: 1,

          justifyContent: 'center',

          alignItems: 'center',

          flexDirection: 'row',

        }}>

        <Pressable

          onPress={() => {

            counterAdd();

          }}

          android_ripple={{color: 'silver'}}

          style={{

            paddingHorizontal: 20,

            paddingVertical: 6,

            backgroundColor: 'silver',

          }}>

          <Text> + </Text>

        </Pressable>

        <Text style={{paddingHorizontal: 6}}> {state} </Text>

        <Pressable

          onPress={() => {

            counterRemove();

          }}

          android_ripple={{color: 'silver'}}

          style={{

            paddingHorizontal: 20,

            paddingVertical: 6,

            backgroundColor: 'silver',

          }}>

          <Text> - </Text>

        </Pressable>

      </View>

    </>

  );

 }

3. Then will add a component which we added as parent component.

export default class ErrorBoundries extends Component {

  constructor(props) {

    super(props);

    this.state = {

      hasError: false,

      error: '',

      errorInfo: '',

    };

  }

  static getDerivedStateFromError(error) {

    return {hasError: true};

  }

  componentDidCatch(error, errorInfo) {

    console.log('Error: ' + error);

    console.log('Error Info: ' + JSON.stringify(errorInfo));

    this.setState({

      error: error,

      errorInfo: errorInfo,

    });

  }

  render() {

    if (this.state.hasError) {

      return (

        <View

          style={{

            flex: 1,

            justifyContent: 'center',

            alignItems: 'center',

          }}>

          <Text>Oops!!! Something went wrong..</Text>

          <Text>Error: {this.state.error.toString()}</Text>

          <Text>Error Info: {JSON.stringify(this.state.errorInfo)}</Text>

        </View>

      );

    }

    return this.props.children;

  }

 }

So we have Implemented Error Boundaries in React Native

The Problem without Error Boundaries :

Javascript errors corrupt component’s internal state and it will cause errors on the next renders, If any run time error occurs react will unmount the whole component tree and show the errors.

Important Notes:

  1. Error Boundaries does not catch errors for Event handlers, Asynchronous code (for ex. setTimeout), Server-side rendering.
  2. Error boundaries do not catch errors for Errors thrown in the error boundary itself.

Conclusion

This article is helpful for developers who want to implement the error boundaries in React Native components. Implementing an error boundary prevents unexpected app behavior and ultimately throws users out of the app upon an error.

Also, readers can find a full example with the help of the below link Github link: https://github.com/ashishgunjal/Error_Boundries_React_Native

Happy Coding!! ūüôāūüôā

Ashish

Tech Expert

Ashish is a React Native Developer with more than 3 years of experience in developing mobile applications. He’s passionate and dedicated to his craft. He is a good team player. He likes to play with JavaScript codes. He worked on a wide range of projects with technologies like React Native, JavaScript, React.js, HTML, CSS, Android, iOS.

The founder's survey report on "What Matters For Startup" is released - Get your copy and learn the trends of successful companies :)

Download Free eBook Now!

Get in touch for a detailed discussion.

Hear From Our 100+ Customers
coma

Mindbowser helped us build an awesome iOS app to bring balance to people's lives.

author
Addie Wootten
CEO, Smiling Mind
coma

We had very close go live timeline and MindBowser team got us live a month before.

author
Shaz Khan
CEO, BuyNow WorldWide
coma

They were a very responsive team! Extremely easy to communicate and work with!

author
Kristen M.
Founder & CEO, TotTech
coma

We‚Äôve had very little-to-no hiccups at all‚ÄĒit‚Äôs been a really pleasurable experience.

author
Chacko Thomas
Co-Founder, TEAM8s
coma

Mindbowser is one of the reasons that our app is successful. These guys have been a great team.

author
Dave Dubier
Founder & CEO, MangoMirror