[{"data":1,"prerenderedAt":134},["ShallowReactive",2],{"qa-\u002Freact\u002Fpatterns\u002Ferror-boundaries":3},{"page":4,"siblings":114,"blog":131},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":105,"related":106,"seo":107,"seoDescription":108,"stem":109,"subtopic":6,"topic":110,"topicSlug":111,"updated":112,"__hash__":113},"qa\u002Freact\u002Fpatterns\u002Ferror-boundaries.md","Error Boundaries",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","React","react",{},true,3,"\u002Freact\u002Fpatterns\u002Ferror-boundaries",[23,28,32,36,40,44,48,52,56,60,64,68,72,77,81,85,89,93,97,101],{"id":24,"difficulty":25,"q":26,"a":27},"what-is-error-boundary","easy","What is an error boundary and what problem does it solve in React?","An **error boundary** is a React class component that catches **JavaScript errors\nanywhere in its child component tree**, logs them, and renders a **fallback UI**\ninstead of crashing the whole application.\n\nBefore error boundaries existed, a single uncaught render error would unmount the\nentire React tree and leave users with a blank screen. Error boundaries provide\n**fault isolation** — only the subtree that threw is replaced with a fallback;\neverything outside the boundary keeps running normally.\n\n```jsx\n\u002F\u002F Without an error boundary, one bad render kills the whole app.\n\u002F\u002F With one, only the ErrorWidget section crashes — the rest survives.\n\u003CApp>\n  \u003CHeader \u002F>           {\u002F* still renders fine *\u002F}\n  \u003CErrorBoundary fallback={\u003Cp>Widget failed.\u003C\u002Fp>}>\n    \u003CErrorWidget \u002F>    {\u002F* throws → caught here, fallback shown *\u002F}\n  \u003C\u002FErrorBoundary>\n  \u003CFooter \u002F>           {\u002F* still renders fine *\u002F}\n\u003C\u002FApp>\n```\n\n**Rule of thumb:** An error boundary is a circuit breaker — it stops one bad\ncomponent from taking down the entire user interface.\n",{"id":29,"difficulty":14,"q":30,"a":31},"getDerivedStateFromError","What does getDerivedStateFromError do and when is it called?","`getDerivedStateFromError` is a **static lifecycle method** called during the\n**render phase** when a descendant throws. It receives the thrown error and must\nreturn an object that is merged into the component's state — typically a flag\nthat switches the component from rendering children to rendering the fallback UI.\n\nBecause it runs during the render phase it must be **pure and side-effect free**.\nUse it only to update state; do all logging in `componentDidCatch` instead.\n\n```jsx\nclass ErrorBoundary extends React.Component {\n  state = { hasError: false, error: null };\n\n  \u002F\u002F Called during render phase — update state to trigger fallback\n  static getDerivedStateFromError(error) {\n    return { hasError: true, error }; \u002F\u002F pure — no side effects here\n  }\n\n  render() {\n    if (this.state.hasError) {\n      return \u003Cp>Something went wrong.\u003C\u002Fp>; \u002F\u002F fallback UI\n    }\n    return this.props.children; \u002F\u002F normal path\n  }\n}\n```\n\n**Rule of thumb:** `getDerivedStateFromError` answers *what* to show; it must\nstay pure — keep it to one `return` statement that updates state.\n",{"id":33,"difficulty":14,"q":34,"a":35},"componentDidCatch","What is componentDidCatch and how does it differ from getDerivedStateFromError?","`componentDidCatch` is called during the **commit phase**, after the fallback UI\nhas been painted. Unlike `getDerivedStateFromError` it receives both the **error**\nand an **info object** (`{ componentStack }`) that contains the component stack\ntrace. It is the right place for **side effects** such as logging to an error\nmonitoring service.\n\nThe two methods are complementary: `getDerivedStateFromError` flips the state to\nshow the fallback; `componentDidCatch` does the logging.\n\n```jsx\nclass ErrorBoundary extends React.Component {\n  state = { hasError: false };\n\n  static getDerivedStateFromError() {\n    return { hasError: true }; \u002F\u002F render phase — only flip the flag\n  }\n\n  componentDidCatch(error, info) {\n    \u002F\u002F Commit phase — side effects are safe here\n    \u002F\u002F info.componentStack is the React component call stack\n    logErrorToSentry(error, { extra: { componentStack: info.componentStack } });\n  }\n\n  render() {\n    return this.state.hasError\n      ? \u003CFallbackUI \u002F>\n      : this.props.children;\n  }\n}\n```\n\n**Rule of thumb:** `getDerivedStateFromError` = pure state update (render phase);\n`componentDidCatch` = side effects like logging (commit phase). Use both together.\n",{"id":37,"difficulty":14,"q":38,"a":39},"why-class-component","Why must error boundaries be class components? Is there a hook-based alternative?","Error boundaries require `getDerivedStateFromError` and `componentDidCatch`, which\nare **class lifecycle methods** with no hook equivalents in React's public API. The\nReact team has acknowledged this gap but has not shipped a functional replacement —\nas of React 18 you still need a class component.\n\nThe `react-error-boundary` library wraps a class boundary behind a friendly\nfunctional API, which is the recommended way to avoid writing class components\nyourself in modern codebases.\n\n```jsx\n\u002F\u002F The class is unavoidable at the boundary itself…\nclass ErrorBoundary extends React.Component {\n  state = { hasError: false };\n  static getDerivedStateFromError() { return { hasError: true }; }\n  render() {\n    return this.state.hasError\n      ? this.props.fallback\n      : this.props.children;\n  }\n}\n\n\u002F\u002F …but you can wrap it so callers use a clean functional component:\nfunction SafeWidget({ children }) {\n  return (\n    \u003CErrorBoundary fallback={\u003Cp>Widget failed\u003C\u002Fp>}>\n      {children}\n    \u003C\u002FErrorBoundary>\n  );\n}\n```\n\n**Rule of thumb:** You need a class somewhere in the chain — use\n`react-error-boundary` to hide it so the rest of your codebase stays functional.\n",{"id":41,"difficulty":14,"q":42,"a":43},"errors-not-caught","What types of errors are NOT caught by error boundaries?","Error boundaries catch errors that occur during **rendering, lifecycle methods, and\nconstructors of class components** in the tree below them. They do NOT catch:\n\n- **Event handlers** — React does not call event handlers during rendering; wrap\n  them in a regular `try\u002Fcatch` instead.\n- **Asynchronous code** — errors in `setTimeout`, Promises, or `async\u002Fawait` are\n  not caught because they happen outside React's call stack.\n- **Server-side rendering** — boundaries only work client-side.\n- **Errors thrown inside the boundary itself** — a boundary cannot catch its own\n  render errors.\n\n```jsx\nfunction BadButton() {\n  const handleClick = () => {\n    try {\n      riskyOperation(); \u002F\u002F must use try\u002Fcatch — boundary won't catch this\n    } catch (err) {\n      reportError(err);\n    }\n  };\n  return \u003Cbutton onClick={handleClick}>Go\u003C\u002Fbutton>;\n}\n\nasync function fetchData() {\n  \u002F\u002F Promise rejection — NOT caught by error boundary\n  \u002F\u002F Use .catch() or try\u002Fcatch inside useEffect instead\n  const data = await api.get('\u002Fthings');\n}\n```\n\n**Rule of thumb:** If the error happens outside a React render call — in a\ncallback or a Promise — an error boundary will not catch it.\n",{"id":45,"difficulty":14,"q":46,"a":47},"error-boundary-granularity","At what granularity should you place error boundaries in an application?","**Coarser boundaries** protect large sections but may hide too much on failure.\n**Finer boundaries** give surgical fallbacks but add boilerplate. A typical\nthree-level strategy works well:\n\n1. **App\u002Froot level** — one top-level boundary as a last resort fallback (blank\n   screen prevention).\n2. **Route\u002Fpage level** — a boundary per route so a broken page doesn't kill\n   navigation.\n3. **Widget\u002Ffeature level** — boundaries around independent sidebar panels,\n   recommendation carousels, or ad slots that can fail without affecting the\n   main content.\n\n```jsx\n\u003CRootErrorBoundary>        {\u002F* level 1 — last resort *\u002F}\n  \u003CRouter>\n    \u003CRoutes>\n      \u003CRoute                 \u002F* level 2 — per route *\u002F\n        element={\n          \u003CRouteErrorBoundary>\n            \u003CDashboardPage \u002F>\n          \u003C\u002FRouteErrorBoundary>\n        }\n      \u002F>\n    \u003C\u002FRoutes>\n    \u003CSidebar>\n      \u003CWidgetErrorBoundary> {\u002F* level 3 — isolated widget *\u002F}\n        \u003CRecommendationsPanel \u002F>\n      \u003C\u002FWidgetErrorBoundary>\n    \u003C\u002FSidebar>\n  \u003C\u002FRouter>\n\u003C\u002FRootErrorBoundary>\n```\n\n**Rule of thumb:** Place a boundary wherever you can write a meaningful, scoped\nfallback message — the finer the boundary, the better the user experience.\n",{"id":49,"difficulty":25,"q":50,"a":51},"fallback-ui-design","What should a good fallback UI include?","A well-designed fallback UI tells users **what happened**, **what they can do\nnext**, and ideally provides a **recovery action** (reload, retry, go home).\nAvoid exposing raw error messages or stack traces in production.\n\nGood fallback UIs are:\n- **Scoped** — show only in the crashed section, not full-page unless necessary.\n- **Actionable** — include a retry button or a link to the home page.\n- **Branded** — styled consistently, not a plain white box.\n- **Non-alarming** — phrase errors in friendly, non-technical language.\n\n```jsx\nfunction FallbackUI({ error, resetErrorBoundary }) {\n  return (\n    \u003Cdiv role=\"alert\" className=\"error-panel\">\n      \u003Ch2>This section couldn't load.\u003C\u002Fh2>\n      {\u002F* Never show error.message to users in production *\u002F}\n      \u003Cp>Try refreshing or come back later.\u003C\u002Fp>\n      \u003Cbutton onClick={resetErrorBoundary}>Try again\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n**Rule of thumb:** A fallback UI should answer \"what broke and what can I do?\" —\nnever dump a raw error message onto users.\n",{"id":53,"difficulty":14,"q":54,"a":55},"error-recovery-reset","How do you implement error recovery — letting the user retry after a crash?","Recovery works by **resetting the boundary's error state** so it re-renders its\nchildren on the next render. In a hand-rolled boundary, expose a `reset` method\nor pass a `onReset` callback. In `react-error-boundary`, use the\n`resetErrorBoundary` prop injected into the fallback component.\n\nThe key subtlety: if the component that threw hasn't changed, it will throw again\nimmediately. Pair the reset with a **key change** or a data refetch so the\nre-render has a chance to succeed.\n\n```jsx\nclass ErrorBoundary extends React.Component {\n  state = { hasError: false };\n\n  static getDerivedStateFromError() { return { hasError: true }; }\n\n  \u002F\u002F Expose reset so parent or fallback can call it\n  reset = () => this.setState({ hasError: false });\n\n  render() {\n    if (this.state.hasError) {\n      return (\n        \u003CFallbackUI onRetry={this.reset} \u002F>  \u002F\u002F pass reset down\n      );\n    }\n    return this.props.children;\n  }\n}\n```\n\n**Rule of thumb:** Always give users a retry path — but also make sure the retry\nactually fixes the underlying condition, not just re-throws the same error.\n",{"id":57,"difficulty":14,"q":58,"a":59},"react-error-boundary-library","What does the react-error-boundary library provide over a hand-rolled boundary?","`react-error-boundary` is the community-standard wrapper that adds four key\nfeatures on top of the raw class API:\n\n1. **`\u003CErrorBoundary>`** — a ready-made class boundary that accepts `fallback`,\n   `FallbackComponent`, `onError`, `onReset`, and `resetKeys` props.\n2. **`FallbackComponent`** — receives `{ error, resetErrorBoundary }` so the\n   fallback can trigger recovery without prop drilling.\n3. **`resetKeys`** — an array of values; when any changes the boundary\n   auto-resets, enabling data-driven recovery.\n4. **`useErrorBoundary()`** — hook that lets any functional component throw\n   errors up to the nearest boundary programmatically (useful for async errors).\n\n```jsx\nimport { ErrorBoundary } from 'react-error-boundary';\n\nfunction Fallback({ error, resetErrorBoundary }) {\n  return (\n    \u003Cdiv role=\"alert\">\n      \u003Cp>Error: {error.message}\u003C\u002Fp>\n      \u003Cbutton onClick={resetErrorBoundary}>Retry\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  );\n}\n\n\u002F\u002F resetKeys: boundary auto-resets whenever `userId` changes\n\u003CErrorBoundary FallbackComponent={Fallback} resetKeys={[userId]}>\n  \u003CUserProfile userId={userId} \u002F>\n\u003C\u002FErrorBoundary>\n```\n\n**Rule of thumb:** Use `react-error-boundary` in production — it removes the need\nto write class components and handles the reset logic correctly.\n",{"id":61,"difficulty":14,"q":62,"a":63},"useErrorBoundary-hook","How does useErrorBoundary let functional components interact with an error boundary?","`useErrorBoundary` (from `react-error-boundary`) returns\n`{ showBoundary, resetBoundary }`. Calling `showBoundary(error)` throws the error\nup to the nearest `\u003CErrorBoundary>` as if it had been thrown during rendering.\nThis is the standard way to route **async and event-handler errors** through a\nboundary, since those errors are not caught automatically.\n\n```jsx\nimport { useErrorBoundary } from 'react-error-boundary';\n\nfunction UserList() {\n  const { showBoundary } = useErrorBoundary();\n\n  useEffect(() => {\n    fetchUsers()\n      .then(setUsers)\n      .catch((err) => {\n        showBoundary(err); \u002F\u002F manually escalate to nearest boundary\n      });\n  }, []);\n\n  return \u003Cul>{\u002F* ... *\u002F}\u003C\u002Ful>;\n}\n```\n\n**Rule of thumb:** Use `showBoundary` from `useErrorBoundary` any time you need\nto route a non-render error (async, event handler) into the boundary system.\n",{"id":65,"difficulty":14,"q":66,"a":67},"resetKeys-prop","What is the resetKeys prop in react-error-boundary and when should you use it?","`resetKeys` is an array of values passed to `\u003CErrorBoundary>`. Whenever any value\nin the array **changes between renders**, the boundary automatically resets its\nerror state and re-renders its children. This enables **data-driven recovery**\nwithout requiring the user to click a retry button.\n\nCommon use cases: resetting when the user navigates to a different resource\n(changing `userId`, `postId`), or when a query key changes after a refetch.\n\n```jsx\n\u002F\u002F Automatically retry when the user switches to a different profile\n\u003CErrorBoundary\n  FallbackComponent={ProfileError}\n  resetKeys={[userId]}       \u002F\u002F boundary resets whenever userId changes\n  onReset={() => refetch()}  \u002F\u002F also trigger a fresh network request\n>\n  \u003CUserProfile userId={userId} \u002F>\n\u003C\u002FErrorBoundary>\n```\n\n**Rule of thumb:** Use `resetKeys` when navigating between resources — it gives\nevery new resource a clean slate without manual reset button clicks.\n",{"id":69,"difficulty":14,"q":70,"a":71},"logging-to-sentry","How do you log errors to an external service like Sentry inside componentDidCatch?","`componentDidCatch` is the correct hook for external logging because it runs\nduring the **commit phase** where side effects are safe. It receives both the\n`error` and `info.componentStack`, which together give a useful trace for\ndebugging. Pass both to your monitoring SDK.\n\nWith `react-error-boundary`, use the `onError` prop instead of subclassing.\n\n```jsx\nimport * as Sentry from '@sentry\u002Freact';\n\n\u002F\u002F Option 1: hand-rolled class boundary\ncomponentDidCatch(error, info) {\n  Sentry.captureException(error, {\n    extra: { componentStack: info.componentStack },\n  });\n}\n\n\u002F\u002F Option 2: react-error-boundary — onError prop (preferred)\n\u003CErrorBoundary\n  FallbackComponent={Fallback}\n  onError={(error, info) => {\n    Sentry.captureException(error, {\n      extra: { componentStack: info.componentStack },\n    });\n  }}\n>\n  \u003CApp \u002F>\n\u003C\u002FErrorBoundary>\n```\n\n**Rule of thumb:** Always log both the error *and* the component stack —\n`error.message` tells you what crashed; `componentStack` tells you where.\n",{"id":73,"difficulty":74,"q":75,"a":76},"error-boundary-with-suspense","hard","How do error boundaries work alongside React Suspense?","`\u003CSuspense>` handles **loading states** (a component \"suspends\" by throwing a\nPromise); error boundaries handle **error states** (a component throws an Error).\nThe two are designed to compose: wrap a `\u003CSuspense>` inside an `\u003CErrorBoundary>`\nto cover both loading and failure for the same subtree.\n\nIn concurrent mode, React can retry suspended trees. If a retry results in an\nError (not a Promise), the nearest error boundary catches it.\n\n```jsx\n\u002F\u002F Layered: error boundary wraps Suspense — covers both failure modes\n\u003CErrorBoundary FallbackComponent={ErrorFallback}>\n  \u003CSuspense fallback={\u003CSpinner \u002F>}>\n    {\u002F* LazyComponent suspends while loading → shows Spinner     *\u002F}\n    {\u002F* If it throws an Error instead → ErrorBoundary catches it *\u002F}\n    \u003CLazyComponent \u002F>\n  \u003C\u002FSuspense>\n\u003C\u002FErrorBoundary>\n```\n\n**Rule of thumb:** Wrap every `\u003CSuspense>` in an `\u003CErrorBoundary>` — Suspense\nonly handles the \"pending\" state; errors still need a boundary.\n",{"id":78,"difficulty":74,"q":79,"a":80},"boundary-in-concurrent-mode","Does concurrent mode (React 18) change how error boundaries behave?","Concurrent React introduces **partial rendering** and **retries**, which changes\nsome boundary behavior:\n\n- React may attempt to render a subtree **multiple times** before committing, so\n  `getDerivedStateFromError` might be called more than once for the same error.\n  The method must remain pure.\n- With `startTransition`, React can **defer** a failing render and keep the\n  previous UI visible rather than immediately showing the boundary fallback,\n  giving a smoother degradation.\n- In **Strict Mode (development only)** React double-invokes render to surface\n  impure code — `componentDidCatch` is *not* double-invoked, but\n  `getDerivedStateFromError` may be.\n\n```jsx\n\u002F\u002F Wrap a non-urgent update in a transition:\n\u002F\u002F if it errors, React keeps showing the stale UI instead of the fallback\nconst [isPending, startTransition] = useTransition();\n\nstartTransition(() => {\n  setResourceId(newId); \u002F\u002F error here → boundary catches, but only after transition\n});\n```\n\n**Rule of thumb:** Keep `getDerivedStateFromError` pure — concurrent mode may\ncall it multiple times before a single commit.\n",{"id":82,"difficulty":74,"q":83,"a":84},"error-boundary-itself-throws","What happens if an error boundary's own render method throws?","A boundary **cannot catch its own errors**. If `render()` or any lifecycle in the\nboundary class itself throws, React walks up the tree and looks for the next\nancestor error boundary. If none exists, the entire React tree is unmounted.\n\nThis means every error boundary implicitly relies on its parent being error-free —\nor being wrapped in another boundary. In practice, nest a minimal top-level\nboundary (that itself contains no complex logic) as the outermost root to catch\nanything a deeper boundary misses.\n\n```jsx\n\u002F\u002F A boundary that itself might fail — bad practice:\nclass RiskyBoundary extends React.Component {\n  static getDerivedStateFromError() { return { hasError: true }; }\n  render() {\n    if (this.state.hasError) {\n      return \u003CComplexFallbackThatMightAlsoThrow \u002F>; \u002F\u002F dangerous!\n    }\n    return this.props.children;\n  }\n}\n\n\u002F\u002F Keep fallback UI extremely simple — plain HTML, no data fetching:\nrender() {\n  if (this.state.hasError) {\n    return \u003Cp>Something went wrong.\u003C\u002Fp>; \u002F\u002F safe, cannot throw\n  }\n  return this.props.children;\n}\n```\n\n**Rule of thumb:** Keep fallback UI dead simple — it should be plain HTML or a\nstatic string, never something that fetches data or renders lazily.\n",{"id":86,"difficulty":14,"q":87,"a":88},"testing-error-boundaries","How do you test an error boundary with React Testing Library?","The standard approach is to render a component that **intentionally throws** and\nassert that the fallback UI appears. React Testing Library does not suppress the\nconsole error from React's internal boundary reporting, so you should spy on\n`console.error` and suppress it to keep test output clean.\n\n```jsx\nimport { render, screen } from '@testing-library\u002Freact';\nimport { ErrorBoundary } from 'react-error-boundary';\n\n\u002F\u002F A component that always throws\nfunction Bomb() {\n  throw new Error('💥 test error');\n}\n\ntest('renders fallback when child throws', () => {\n  \u002F\u002F Suppress React's console.error noise in test output\n  const spy = jest.spyOn(console, 'error').mockImplementation(() => {});\n\n  render(\n    \u003CErrorBoundary fallback={\u003Cp>Boundary caught it\u003C\u002Fp>}>\n      \u003CBomb \u002F>\n    \u003C\u002FErrorBoundary>\n  );\n\n  expect(screen.getByText('Boundary caught it')).toBeInTheDocument();\n  spy.mockRestore(); \u002F\u002F always restore after test\n});\n```\n\n**Rule of thumb:** Suppress `console.error` during boundary tests to keep output\nclean, but always restore the spy — suppressing it globally hides real issues.\n",{"id":90,"difficulty":14,"q":91,"a":92},"testing-reset-behavior","How do you test the reset\u002Fretry behavior of an error boundary?","Test recovery by simulating the retry action (clicking the button) and asserting\nthat the children render successfully after the error condition is cleared. Use\na **stateful wrapper** to toggle whether the child throws, simulating a data fix.\n\n```jsx\nlet shouldThrow = true;\n\nfunction MaybeThrow() {\n  if (shouldThrow) throw new Error('temporary failure');\n  return \u003Cp>Content loaded\u003C\u002Fp>;\n}\n\ntest('retries successfully after reset', async () => {\n  const spy = jest.spyOn(console, 'error').mockImplementation(() => {});\n\n  render(\n    \u003CErrorBoundary FallbackComponent={({ resetErrorBoundary }) => (\n      \u003Cbutton onClick={() => {\n        shouldThrow = false;     \u002F\u002F fix the condition before reset\n        resetErrorBoundary();    \u002F\u002F trigger boundary reset\n      }}>Retry\u003C\u002Fbutton>\n    )}>\n      \u003CMaybeThrow \u002F>\n    \u003C\u002FErrorBoundary>\n  );\n\n  await userEvent.click(screen.getByText('Retry'));\n  expect(screen.getByText('Content loaded')).toBeInTheDocument();\n  spy.mockRestore();\n});\n```\n\n**Rule of thumb:** Fix the error condition *before* calling `resetErrorBoundary`\n— otherwise the boundary resets and immediately throws again.\n",{"id":94,"difficulty":25,"q":95,"a":96},"error-boundary-vs-try-catch","When should you use an error boundary vs a try\u002Fcatch block in React code?","**Error boundaries** protect against uncaught errors in the **render cycle** —\nthey intercept errors in `render`, lifecycle methods, and constructors. They\nprovide a declarative, component-scoped safety net.\n\n**try\u002Fcatch** is for **imperative code** — event handlers, async operations,\nand utility functions outside the React render cycle where boundaries cannot reach.\n\n| Scenario | Tool |\n|---|---|\n| Component throws during render | Error boundary |\n| `async` fetch in `useEffect` | try\u002Fcatch + state |\n| Button click handler throws | try\u002Fcatch |\n| Lazy-loaded component fails | Error boundary + Suspense |\n\n```jsx\n\u002F\u002F Render error → boundary handles it automatically\nfunction BadRender() {\n  const data = JSON.parse(null); \u002F\u002F throws during render → boundary catches\n  return \u003Cdiv>{data.name}\u003C\u002Fdiv>;\n}\n\n\u002F\u002F Async error → try\u002Fcatch needed\nasync function loadUser(id) {\n  try {\n    return await api.getUser(id);\n  } catch (err) {\n    showBoundary(err); \u002F\u002F escalate manually via useErrorBoundary\n  }\n}\n```\n\n**Rule of thumb:** Use boundaries for render errors, try\u002Fcatch for everything\nelse — then bridge async failures into boundaries via `showBoundary`.\n",{"id":98,"difficulty":25,"q":99,"a":100},"multiple-boundaries-strategy","Can you have multiple error boundaries in the same component tree? How should they be nested?","Yes — React will propagate an unhandled error **up the tree** until it finds the\nnearest ancestor error boundary. Multiple nested boundaries each act as\nindependent catch points for their own subtrees.\n\nA healthy app has **multiple boundaries at different levels**:\n\n- The root boundary is the final backstop.\n- Route-level boundaries isolate page failures.\n- Widget-level boundaries isolate autonomous sections.\n\n```jsx\n\u002F\u002F Each boundary is independent — inner boundary failing falls up to outer\n\u003CAppBoundary>          {\u002F* outer: catches everything the inner misses *\u002F}\n  \u003CLayout>\n    \u003CNavBoundary>      {\u002F* isolates nav errors *\u002F}\n      \u003CNavigation \u002F>\n    \u003C\u002FNavBoundary>\n\n    \u003CPageBoundary>     {\u002F* isolates current page errors *\u002F}\n      \u003CMainContent>\n        \u003CWidgetBoundary> {\u002F* isolates a single widget *\u002F}\n          \u003CLiveFeed \u002F>\n        \u003C\u002FWidgetBoundary>\n      \u003C\u002FMainContent>\n    \u003C\u002FPageBoundary>\n  \u003C\u002FLayout>\n\u003C\u002FAppBoundary>\n```\n\n**Rule of thumb:** Think of boundaries like `try\u002Fcatch` nesting — the innermost\nmatching boundary catches the error; outer ones only fire if the inner one itself\nfails or doesn't exist.\n",{"id":102,"difficulty":25,"q":103,"a":104},"production-vs-development","Why do error boundaries behave differently in development vs production?","In **development** (`react-dom\u002Fdevelopment`), React re-throws errors after calling\nthe boundary so that the browser's DevTools overlay and the console both show the\nfull stack trace. This means you'll see the error in the console **even when a\nboundary catches it** — that's intentional, not a bug.\n\nIn **production** (`react-dom\u002Fproduction`), the error is caught silently by the\nboundary, the fallback UI is shown, and no overlay appears. Users see only the\nfallback; developers see nothing unless logging (Sentry, etc.) is set up.\n\n```jsx\n\u002F\u002F Dev: React error overlay appears + console.error fires even with a boundary.\n\u002F\u002F This tells developers the error happened; the boundary still works in prod.\n\n\u002F\u002F A common mistake: developers test boundaries in dev, see the overlay,\n\u002F\u002F and think the boundary isn't working — it is; the overlay is just dev behavior.\n\ncomponentDidCatch(error, info) {\n  \u002F\u002F This is your ONLY visibility into boundary-caught errors in production\n  logToMonitoringService(error, info);\n}\n```\n\n**Rule of thumb:** The dev error overlay does not mean the boundary failed —\nReact shows it deliberately; always test production behavior with `npm run build`.\n",20,null,{"description":11},"React error boundary interview questions — componentDidCatch, getDerivedStateFromError, fallback UI, error recovery, async errors, and react-error-boundary library.","react\u002Fpatterns\u002Ferror-boundaries","Patterns","patterns","2026-06-24","HclcDy5UUQv4iAGr42ulavhLi8--jWKoMfQiQ1_LMnU",[115,119,122,123,127],{"subtopic":116,"path":117,"order":118},"Compound Components","\u002Freact\u002Fpatterns\u002Fcompound-components",1,{"subtopic":120,"path":121,"order":12},"Render Props & HOCs","\u002Freact\u002Fpatterns\u002Frender-props-hoc",{"subtopic":6,"path":21,"order":20},{"subtopic":124,"path":125,"order":126},"Portals & Refs","\u002Freact\u002Fpatterns\u002Fportals-refs",4,{"subtopic":128,"path":129,"order":130},"forwardRef & useImperativeHandle","\u002Freact\u002Fpatterns\u002Fforward-ref-imperative",5,{"path":132,"title":133},"\u002Fblog\u002Freact-error-boundaries-guide","React Error Boundaries — Complete Interview Guide",1782244101289]