How to Debug a React Application in VS Code (Complete Guide)
Step-by-step guide to debugging React apps in VS Code — component errors, hooks bugs, state issues, and network failures — using DevTools and the VS Code debugger
React Debugging Happens in Two Places
React apps have two debugging environments: browser DevTools (for component state, network, runtime errors) and VS Code (for breakpoints and step-through debugging). Both are useful for different problems.
Use browser DevTools for:
- Reading error messages and component stacks
- Inspecting state and props in React DevTools
- Watching network requests
- Console logging
Use VS Code debugger for:
- Setting breakpoints in event handlers and useEffect
- Stepping through complex logic line by line
- Inspecting variable state without console.log spam
Step 1: Read the Error Overlay
React dev mode shows a red error overlay with the component stack when an unhandled error occurs. The component stack reads bottom-up:
Start from ProductCard at line 18. Go to that line — that's where the error fires. The parent (ProductList line 34) is where ProductCard received the undefined prop.
Step 2: Install React DevTools
React DevTools is a browser extension (Chrome + Firefox) that adds two panels to DevTools:
- Components — see the full component tree, inspect each component's props and state in real time
- Profiler — record a session and see which components re-rendered and how long they took
For props/state bugs: open Components panel → click the component → see current state on the right. Change state directly to test behavior without modifying code.
Tip: In the Components panel, right-click a component → "Log this component's data to the console". Gets you a full snapshot of props and state as a JS object — easier to inspect complex nested state.
Step 3: Set Up VS Code Debugger for React
Create .vscode/launch.json in your project root:
Start your dev server (npm run dev) then press F5 in VS Code. Chrome launches, controlled by VS Code. Set breakpoints in .jsx/.tsx files — execution pauses in VS Code when that line runs.
Note: For Vite-based projects, the url port is 5173 not 3000. Check your terminal for the correct port.
Step 4: Debug useEffect
useEffect is the most common source of React bugs. Common patterns:
Fix: Always include dependency array. Primitives (string, number, boolean) are safe. Objects and arrays need
useMemoor move inside the effect.
Set a breakpoint inside useEffect to see how many times it runs:
Remove debugger before commit. It's a fast way to check effect frequency without adding console.log.
Step 5: Debug State Issues
When state looks wrong, the problem is almost always one of three things:
Stale closure:
Fix: Use functional update form, or include count in dependency array.
State mutation (React doesn't detect):
Fix: Always return new references.
Step 6: Debug Network Requests
Open DevTools → Network tab → filter by "Fetch/XHR". Every API call your React app makes appears here.
For each failed request, check:
- Status code — 401 means auth, 422 means validation, 500 means server error
- Response body — the actual error message from the server
- Request headers — is Authorization header present? Correct format?
- Request body — is the payload what you expected?
Tip: Click a request → "Copy as cURL" → paste in terminal. Reproduces the exact request outside the browser. If it works in terminal but fails in browser, CORS or auth header issue.
Step 7: Debug Custom Hooks
Custom hooks are functions — debug them like functions. Add a breakpoint at the first line of the hook, or return debug info alongside the main return value:
In React DevTools Components panel, find the component using the hook — its state shows the hook's state values directly.
Common React Errors Quick Reference
| Error | Likely cause | First check |
|---|---|---|
| Cannot read properties of undefined | Prop is undefined, accessing property too early | Check parent passes prop, add optional chaining |
| Each child in a list should have a unique key | List rendered without stable key | Add key={item.id} (not array index) |
| Infinite re-render | useEffect dependency causes re-render which triggers effect | Check effect dependencies, memoize objects |
| Stale data in handler | Stale closure capturing old state | Use functional update setState(prev => ...) |
| Component doesn't update | State mutation | Return new array/object instead of mutating |
| Rendered more hooks than previous render | Hooks called conditionally | Move hook calls before any early returns |
For cross-component state bugs — where state passes through 3+ components and arrives wrong at the bottom — paste the component tree into DebugAI. It reads the prop-drilling chain and identifies where the value changes or gets lost.
Debug faster starting today.
Free VS Code extension. 10 sessions/day. No credit card.