Error Boundary is a React component that catches JavaScript errors in its child component tree and displays a fallback interface instead of a crash page. In the context of React Native, it prevents a complete app crash during non-fatal rendering errors. According to React Documentation, 2024, error boundary catches errors in render methods, lifecycle hooks, and constructors of child components, allowing the application to continue working. In React Native this is especially critical because a mobile app cannot be reloaded with F5 — the user loses their entire session.
Key Takeaways
Error Boundary is a React mechanism for graceful degradation during rendering errors. Introduced in React 16 (2017) as a wrapper component implementing one of two lifecycle methods: static getDerivedStateFromError or componentDidCatch. Error Boundary allows showing the user a meaningful message instead of a blank white screen or a complete app crash.
Before React 16, any unhandled error in render would cause a complete app crash with unmounting of the entire DOM tree. In web applications, this meant a blank white screen; in React Native, a complete app crash returning to the Home Screen. The React team introduced Error Boundary as an analog of a catch block for declarative UI, borrowing the concept from the “let it crash” approach in the Erlang language.
In React Native, the absence of Error Boundary means a complete app crash on any rendering error. The user loses their entire current session without recovery options. Error Boundary in React Native is critically important because mobile apps cannot be reloaded like web pages — the user session is irretrievably lost, and the user has to start over from scratch.
Error Boundary works at the React tree level. When a child component throws an error in render or lifecycle, React does not unmount the entire tree but passes control to the nearest Error Boundary higher in the hierarchy. The Boundary calls getDerivedStateFromError, sets state.hasError = true, and renders fallback UI instead of the broken component branch.
import React, { Component, ErrorInfo, ReactNode } from "react"
interface Props {
children: ReactNode
fallback?: ReactNode
}
interface State {
hasError: boolean
error?: Error
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error }
}
componentDidCatch(error: Error, info: ErrorInfo) {
console.error("Caught by boundary:", error)
Crashlytics.recordException(error)
}
render() {
if (this.state.hasError) {
return this.props.fallback || <FallbackUI />
}
return this.props.children
}
}
getDerivedStateFromError sets the state for rendering fallback UI — this is a static method called during the render phase before committing changes. componentDidCatch executes during the commit phase and is intended for side effects: logging, sending crash reports to Crashlytics, analytics. The two methods separate responsibility between UI state management and side effects.
To create an Error Boundary, you need to implement a class component with getDerivedStateFromError and/or componentDidCatch methods. Functional components cannot be Error Boundary — React supports this functionality only for class components because access to lifecycle methods is required. The react-error-boundary library provides a ready-made implementation with a hook-based API for convenience.
// Error Boundary usage example in React Native
import { ErrorBoundary } from "react-error-boundary"
const FallbackComponent = ({ error, resetError }: FallbackProps) => (
<View style={styles.container}>
<Text>Something went wrong</Text>
<Text>{error.message}</Text>
<Button title="Retry" onPress={resetError} />
</View>
)
const App = () => (
<SafeAreaView>
<ErrorBoundary FallbackComponent={<FallbackComponent />}>
<UserProfile userId={"123"} />
</ErrorBoundary>
<BottomNavigation />
</SafeAreaView>
)
Wrapper Levels — Error Boundary can be placed at different hierarchy levels. One global Boundary at the app root will show fallback UI on any error, but navigation will still be preserved. Multiple Boundaries at the screen level allow isolating errors: if one screen breaks, the rest continue working independently. react-error-boundary simplifies the reset mechanism through the useErrorBoundary hook, allowing state reset without reloading. For typical projects, a three-level Boundary scheme is considered optimal for React Native applications.
After an error occurs, the user can click the “Retry” button, which resets hasError to false and re-renders the child tree. The Reset mechanism is important for restoring application functionality without reloading. In react-error-boundary, the onReset callback is used, which can clear cache, re-fetch data, or update state higher up the tree.
Error Boundary does not catch asynchronous errors — errors in setTimeout, setInterval, Promise, async/await. React cannot intercept errors outside the render cycle and lifecycle hooks because they execute in different execution contexts. For asynchronous errors, a separate try-catch in handlers or a global unhandledrejection event handler is required.
Errors in onClick, onChange, and other event handlers are not caught by Error Boundary because they execute outside React rendering. Error handling for event handlers should be inside the handler itself using try-catch. The react-error-boundary library provides the useErrorHandler hook for throwing errors from event handlers to the nearest Boundary.
Error Boundary does not work on the server side in Next.js or Gatsby. The getDerivedStateFromError and componentDidCatch methods are not called during SSR because lifecycle methods are only available in the browser. For server errors, a separate strategy is required: try-catch in getServerSideProps, error.js fallback pages (Next.js 13+), or global middleware.
In React Native, Error Boundary does not prevent crashes at the native module level. A native crash (segfault, out-of-memory, native exception) occurs at the Objective-C or Java level and does not reach the JavaScript layer. For native crashes, Crashlytics NDK (Android) or KSCrash (iOS) is required. Error Boundary only protects the JavaScript layer of a React Native application.
Place Error Boundary at the boundaries of logical modules: one Boundary per screen, one per third-party widget, one per complex form. This isolates errors and allows the user to continue working in other parts of the application. A root Boundary should always be present — for critical errors in common navigation components or providers. Each Boundary is responsible for its own interface fragment and does not affect neighboring components when an error occurs.
Always pass the error to Crashlytics or Sentry through componentDidCatch. Add context: screen name, userId, app version, navigation parameters. In Sentry, breadcrumbs are available — a sequence of user actions leading to the error. For analyzing the frequency of non-fatal errors, use Crashlytics dashboards with grouping by issue.
Do not use a bare fallback — create a meaningful interface. Recommended set for React Native: error message (user-friendly, not technical), a “Retry” button, a link to support or chat. Avoid an empty View — the user will think the app has crashed completely and will close it. The fallback should be integrated into the overall app design.
Test each Error Boundary using React Testing Library or React Native Testing Library. Create a trigger component that throws an error on render and verify that the fallback UI is displayed. For integration tests, use storybook with different Error Boundary states: normal, error, post-reset state. Automated testing of Boundary ensures that when the component changes, the fallback UI continues to work correctly in production. Test coverage for each Boundary should be a mandatory code review requirement for React Native projects.
Frequently Asked Questions
React implements Error Boundary only through class components because access to the componentDidCatch and getDerivedStateFromError lifecycle methods is required. Functional components do not have such methods. The react-error-boundary library provides a ready-made class wrapper with a hook-based API for ease of use.
The impact is minimal — Error Boundary adds a state check on every render of the child tree. Comparing state.hasError is an O(1) operation with constant complexity. When there are no errors, there is no overhead. Only when an error occurs does the Boundary perform an additional render of the fallback UI.
No, 2–3 levels are sufficient: a root Boundary for the entire application, a screen Boundary for each navigation branch, and a local Boundary for critical widgets (payment form, map, chat). Excessive Boundary usage complicates the architecture without significant benefit.
Error Boundary and Suspense are independent: Suspense catches loading (pending Promise in React 18+), Error Boundary catches rendering errors. They can be combined: <ErrorBoundary><Suspense><Component /></Suspense></ErrorBoundary>. Suspense triggers first during loading, Error Boundary triggers on errors of the loaded component.
try-catch catches errors in synchronous imperative code but cannot intercept JSX rendering errors. Error Boundary is specifically designed for declarative UI: it intercepts errors in render, lifecycle hooks, and constructors of child components, which try-catch cannot do due to the specifics of React rendering.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also