Bird
Raised Fist0
NextJSframework~8 mins

Client-side error boundaries in NextJS - Performance & Optimization

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Performance: Client-side error boundaries
MEDIUM IMPACT
Client-side error boundaries affect interaction responsiveness and visual stability by catching runtime errors without crashing the whole app.
Handling runtime errors in React components to avoid app crashes
NextJS
import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service here
  }

  render() {
    if (this.state.hasError) {
      return <div role="alert">Something went wrong.</div>;
    }

    return this.props.children;
  }
}

function MyComponent() {
  return (
    <ErrorBoundary>
      <ComponentThatMayThrow />
    </ErrorBoundary>
  );
}
Catches errors locally, preventing full app crash and allowing fallback UI, improving interaction responsiveness and visual stability.
📈 Performance GainPrevents blocking rendering on error, reducing INP and CLS by showing fallback UI instead of blank screen.
Handling runtime errors in React components to avoid app crashes
NextJS
function MyComponent() {
  // No error boundary
  const data = JSON.parse('invalid json');
  return <div>{data.name}</div>;
}
No error boundary means any runtime error crashes the entire React tree, causing a blank screen and poor user experience.
📉 Performance CostBlocks rendering completely on error, causing high INP and CLS due to sudden content disappearance.
Performance Comparison
PatternDOM OperationsReflowsPaint CostVerdict
No error boundary (app crash)Full tree unmountMultiple reflows due to remountHigh paint cost for blank screen and reload[X] Bad
Error boundary with fallback UIPartial DOM updateSingle reflow for fallback renderLow paint cost with stable UI[OK] Good
Rendering Pipeline
Error boundaries intercept errors during rendering or lifecycle methods, preventing the error from propagating and crashing the entire React tree. This allows React to render fallback UI instead of unmounting the whole app.
JavaScript Execution
Render
Commit
⚠️ BottleneckJavaScript Execution when error occurs
Core Web Vital Affected
INP, CLS
Client-side error boundaries affect interaction responsiveness and visual stability by catching runtime errors without crashing the whole app.
Optimization Tips
1Always wrap error-prone components with error boundaries to prevent full app crashes.
2Use fallback UI in error boundaries to maintain visual stability and reduce layout shifts.
3Avoid heavy logic inside error boundaries to keep error handling fast and responsive.
Performance Quiz - 3 Questions
Test your performance knowledge
What is the main performance benefit of using client-side error boundaries in React?
AThey reduce the initial bundle size significantly.
BThey speed up the server-side rendering process.
CThey prevent the entire app from crashing and improve interaction responsiveness.
DThey eliminate all JavaScript errors automatically.
DevTools: Performance
How to check: Record a session where an error occurs in your app. Look for long tasks or dropped frames during error handling.
What to look for: Check if the app recovers gracefully with fallback UI instead of full reload or blank screen, indicating error boundaries work.

Practice

(1/5)
1. What is the main purpose of client-side error boundaries in Next.js?
easy
A. To catch errors in UI components and show a fallback UI instead of crashing the whole app
B. To improve server-side rendering speed
C. To handle database connection errors
D. To optimize image loading performance

Solution

  1. Step 1: Understand error boundaries role

    Error boundaries catch errors in parts of the UI to prevent the entire app from crashing.
  2. Step 2: Identify their main effect

    They show a fallback UI so users see a friendly message instead of a broken screen.
  3. Final Answer:

    To catch errors in UI components and show a fallback UI instead of crashing the whole app -> Option A
  4. Quick Check:

    Error boundaries catch UI errors = C [OK]
Hint: Error boundaries catch UI errors and show fallback UI [OK]
Common Mistakes:
  • Confusing error boundaries with server-side features
  • Thinking they handle backend or database errors
  • Assuming they improve performance directly
2. Which of the following is the correct way to define a client-side error boundary component in Next.js using React hooks?
easy
A. function ErrorBoundary({ children }) { try { return children; } catch { return ; } }
B. class ErrorBoundary extends React.Component { render() { return this.props.children; } }
C. function ErrorBoundary() { return
Error
; }
D. const ErrorBoundary = () => { return children; }

Solution

  1. Step 1: Identify hook-based error boundary pattern

    Client-side error boundaries in Next.js use try/catch inside functional components to catch errors during rendering.
  2. Step 2: Check each option

    function ErrorBoundary({ children }) { try { return children; } catch { return ; } } uses try/catch inside a function component returning children or fallback UI, which is correct.
  3. Final Answer:

    function ErrorBoundary({ children }) { try { return children; } catch { return <Fallback />; } } -> Option A
  4. Quick Check:

    Try/catch in function component = A [OK]
Hint: Use try/catch inside functional component for client error boundaries [OK]
Common Mistakes:
  • Using class components instead of functional components
  • Not using try/catch to catch errors
  • Returning children without error handling
3. Given this client-side error boundary component in Next.js:
function ErrorBoundary({ children }) {
  try {
    return children;
  } catch {
    return <div>Error occurred</div>;
  }
}

function BuggyComponent() {
  throw new Error('Bug!');
}

export default function App() {
  return (
    <ErrorBoundary>
      <BuggyComponent />
    </ErrorBoundary>
  );
}

What will be rendered on the page?
medium
A. output
B.
Error occurred
C. Nothing is rendered
D. The app crashes with an uncaught error

Solution

  1. Step 1: Understand error throwing in BuggyComponent

    BuggyComponent throws an error immediately when rendered.
  2. Step 2: Check ErrorBoundary behavior

    ErrorBoundary tries to render children inside try block; error triggers catch block returning fallback UI <div>Error occurred</div>.
  3. Final Answer:

    <div>Error occurred</div> -> Option B
  4. Quick Check:

    Error caught, fallback shown = D [OK]
Hint: Error in child triggers catch, fallback UI renders [OK]
Common Mistakes:
  • Expecting the app to crash instead of showing fallback
  • Thinking children render despite error
  • Confusing output with component name
4. Identify the problem in this client-side error boundary code snippet:
function ErrorBoundary({ children }) {
  try {
    return children;
  } catch (error) {
    console.log(error);
  }
}

export default function App() {
  return (
    <ErrorBoundary>
      <div>Hello</div>
    </ErrorBoundary>
  );
}

What issue will occur when an error happens inside children?
medium
A. The error is caught and fallback UI is shown
B. The error is logged and children still render
C. The app crashes due to syntax error
D. No fallback UI is returned, so the component renders nothing

Solution

  1. Step 1: Analyze catch block behavior

    The catch block logs the error but does not return any UI.
  2. Step 2: Understand React rendering rules

    Without a return in catch, the component returns undefined, rendering nothing on error.
  3. Final Answer:

    No fallback UI is returned, so the component renders nothing -> Option D
  4. Quick Check:

    Missing return in catch = renders nothing [OK]
Hint: Always return fallback UI in catch block [OK]
Common Mistakes:
  • Forgetting to return fallback UI in catch
  • Assuming logging error is enough
  • Expecting children to render after error
5. You want to create a client-side error boundary in Next.js that catches errors in nested components and logs the error before showing fallback UI. Which approach correctly combines error catching, logging, and fallback rendering?
hard
A. function ErrorBoundary({ children }) { try { return children; } catch (error) { return
Something went wrong.
; } }
B. function ErrorBoundary({ children }) { try { return children; } catch { return
Something went wrong.
; } }
C. function ErrorBoundary({ children }) { try { return children; } catch (error) { console.error(error); return
Something went wrong.
; } }
D. function ErrorBoundary({ children }) { try { return children; } catch (error) { console.log('Error caught'); } }

Solution

  1. Step 1: Check error catching and logging

    function ErrorBoundary({ children }) { try { return children; } catch (error) { console.error(error); return
    Something went wrong.; } } catches error, logs it with console.error, then returns fallback UI.
  2. Step 2: Verify fallback UI return

    function ErrorBoundary({ children }) { try { return children; } catch (error) { console.error(error); return
    Something went wrong.
    ; } } returns fallback UI after logging, ensuring user sees message and error is logged.
  3. Final Answer:

    function ErrorBoundary({ children }) { try { return children; } catch (error) { console.error(error); return <div>Something went wrong.</div>; } } -> Option C
  4. Quick Check:

    Error caught, logged, fallback returned = A [OK]
Hint: Catch error, log it, then return fallback UI [OK]
Common Mistakes:
  • Not logging the error before fallback
  • Not returning fallback UI after catching error
  • Logging without returning fallback UI