mediumReact#46

Error boundary component

Prompt

Create an ErrorBoundary class component that catches errors in its child tree. Display a fallback UI with "Something went wrong" and a retry button.

Solution

class ErrorBoundary extends React.Component {
  state = { hasError: false }
  static getDerivedStateFromError() { return { hasError: true } }
  componentDidCatch(error, info) { console.error(error, info) }
  render() {
    if (this.state.hasError) {
      return (
        <View>
          <Text>Something went wrong</Text>
          <Button title="Retry" onPress={() => this.setState({ hasError: false })} />
        </View>
      )
    }
    return this.props.children
  }
}
Mentor's take

Error boundaries exist because an uncaught error during rendering unmounts the entire React tree — one broken product card takes down the whole app. A boundary converts that into a localized fallback: the failed subtree is replaced, everything outside it keeps working.

The two methods map onto React's two-phase render model, and that mapping is the interview answer. getDerivedStateFromError is static and pure because it runs during the render phase, which concurrent React may execute multiple times before committing — its only job is deriving fallback state. componentDidCatch runs in the commit phase, guaranteed once per committed error, so side effects like logging to Sentry belong there. Same split as the componentWill* deprecation: side effects only in commit-phase code.

Boundaries only catch errors thrown during rendering, lifecycle methods, and constructors of the tree below. Event handlers, async callbacks, and setTimeout bodies are not render — use try/catch there (or throw from state inside the handler to route it into render). Retry is just setState({ hasError: false }) to re-attempt the children. This remains a class-component-only API — there is no hook equivalent, which is why libraries like react-error-boundary wrap this exact class. Place boundaries per feature (per screen, per widget), not one global catch-all.

Red flag: Expecting a boundary to catch a failed fetch in an onPress handler. Saying "boundaries catch render-phase errors only" is the line that shows you've actually used one.

Say it: "getDerivedStateFromError is render-phase and pure — derive fallback state; componentDidCatch is commit-phase — log there; and handlers or async errors never reach a boundary."