Skip to solution
easyFrontend

How do you debug React applications?

358 views
01

Understand the problem

Question presented to candidate: "A bug report says a page shows stale data and feels sluggish. Walk me through how you would debug that in a React app."

What a strong answer should cover:

  • A method, not a tool list: reproduce, narrow to a component, then inspect the data flowing into it.
  • React DevTools Components for wrong values — props, state, hooks, context, and the owner chain that answers "where did this come from?".
  • React DevTools Profiler for slow interactions, with "record why each component rendered" enabled.
  • StrictMode as a proactive detector of impure renders and missing effect cleanup, not a nuisance.
  • Error Boundaries to catch render-phase crashes and show a real fallback plus a component stack.
  • Knowing what an Error Boundary does not catch: event handlers, async code, SSR, and errors in the boundary itself.
  • React 19 additions: captureOwnerStack for the chain of components that created an element.
  • Ordinary JavaScript debugging still applies — breakpoints, conditional breakpoints, the network panel.
  • The common root causes worth naming: stale closures, missing effect dependencies, and unstable object or function identities.

Clarifying questions expected:

  • "Does it reproduce in development, or only in production?" — that changes the toolkit entirely.
  • "Is it wrong data, a crash, or slowness?" — the three lead to different tools.

Code / implementation expected: Optional. An Error Boundary is the one piece of code worth being able to write from memory.

debuggingdev toolserror handlingstrictmode
02

Attempt it yourself

Sketch your approach before reading the solution — that's what interviews test.

Nudge consolestandby

Stuck? Beam a request up — the console returns a conceptual nudge that guides your logic without spoiling the implementation.

03

Study the solution

Target Audience: Engineers preparing for React interviews — assumes hooks and component basics. Difficulty: Medium

How to read this doc: Concepts are explained in plain language first, then tagged with 📌 Interview term:. The React 19 debugging API named in section 5 was read off the install

Solution ready — 2 min read

Classified // press E to declassify

04

Explore the playground snippets

An Error Boundary, and the errors it deliberately cannot catch
Run Playground
import { Component, useState } from "react";

// Error Boundaries still require a class — there is no hook equivalent.
class ErrorBoundary extends Component {
  state = { error: null };

  // Render the fallback on the next render after a child throws.
  static getDerivedStateFromError(error) {
    return { error };
  }

  // Side effects belong here: log to Sentry, etc. info.componentStack tells
  // you which component threw, which a plain JS stack trace will not.
  componentDidCatch(error, info) {
    console.log("[boundary] caught:", error.message);
    console.log("[boundary] component stack:", info.componentStack);
  }

  render() {
    if (this.state.error) {
      return (
        <div style={{ padding: 12, border: "1px solid crimson", borderRadius: 6, color: "crimson" }}>
          <strong>Something went wrong:</strong> {this.state.error.message}{" "}
          <button onClick={() => this.setState({ error: null })}>Retry</button>
        </div>
      );
    }
    return this.props.children;
  }
}

// Throws during RENDER — the boundary catches this.
function ExplodesOnRender({ boom }) {
  if (boom) throw new Error("render-phase error");
  return <p>Rendering fine.</p>;
}

// Throws inside an EVENT HANDLER — the boundary does NOT catch this. It is
// ordinary JavaScript and needs try/catch.
function ExplodesOnClick() {
  const [caught, setCaught] = useState(null);
  return (
    <p>
      <button onClick={() => { throw new Error("handler error — boundary will NOT catch this"); }}>
        Throw in a handler (uncaught)
      </button>{" "}
      <button
        onClick={() => {
          try { throw new Error("handler error"); }
          catch (e) { setCaught(e.message); }
        }}
      >
        Throw, but with try/catch
      </button>
      {caught && <em style={{ color: "green" }}> handled: {caught}</em>}
    </p>
  );
}

export default function App() {
  const [boom, setBoom] = useState(false);

  return (
    <div style={{ padding: 24, fontFamily: "system-ui", lineHeight: 1.6 }}>
      <h3>Caught by the boundary</h3>
      <ErrorBoundary>
        <ExplodesOnRender boom={boom} />
      </ErrorBoundary>
      <button onClick={() => setBoom(true)}>Trigger a render error</button>

      <h3>Not caught by the boundary</h3>
      <ErrorBoundary>
        <ExplodesOnClick />
      </ErrorBoundary>

      <p style={{ color: "#666", fontSize: 13 }}>
        The first button is caught and shows a fallback. The first button in the
        second group escapes to the console — Error Boundaries cover the render,
        lifecycle and constructor phases only, never event handlers or async code.
      </p>
    </div>
  );
}
05

Join the discussion

Discussion (0)

Sign in to join the discussion.

No responses yet. Be the first to share what you think.

Transmission complete // awaiting log

KEEP THE
STREAK ALIVE.

Dossier 19 of 119 decoded in the React.js track. One more won't hurt.

Back to track