How do you debug React applications?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
Start with React DevTools, not console.log. It shows the component tree with each component's live props, state, hooks and context — the four things almost every React bug comes down to.
React DevTools
- Components tab. Select a node and edit its props or state in place to reproduce a state you cannot reach by clicking. The right pane also shows rendered by, which is how you find the actual owner of a prop.
- The "why did this render" note. Enable it in settings and DevTools tells you whether it was props, state, a hook, or the parent.
- Profiler tab. Record an interaction and get a flame chart of commits. Wide bars are slow components; bars that light up on an unrelated click are wasted renders.
- Highlight updates on render. A visual flash around anything re-rendering. The fastest way to spot a component re-rendering on every keystroke.
What the common bugs look like
| Symptom | Usually |
|---|---|
| state is stale in a callback | closure over an old render; use the updater form or a ref |
| infinite re-render loop | a setter in the render body, or an object/array dependency recreated each render |
| effect runs twice in dev | StrictMode double-invoking on purpose — it exposes a missing cleanup |
| list items keep the wrong state | key is the array index over a reordered list |
| "Cannot update unmounted component" | async callback resolving after unmount; abort it in cleanup |
| hydration mismatch | render differs between server and client |
Beyond DevTools
Ordinary breakpoints work — put one in the component body and inspect the hook values in scope. debugger inside an effect tells you exactly when it fires and with what dependencies.
An error boundary turns a blank white screen into a readable error plus the component stack:
<ErrorBoundary fallback={<Oops />}>{children}</ErrorBoundary>
For data problems, the Network tab and your query library's own devtools (React Query, Redux DevTools with time-travel) narrow it to "the request is wrong" or "the render is wrong" in one look, which is most of the work.
And the compiler-level help
The ESLint rules react-hooks/rules-of-hooks and react-hooks/exhaustive-deps catch a large share of hook bugs before you ever run the app. StrictMode in development catches the rest by running renders and effects twice — if something breaks under it, it would eventually have broken in production.
