Debugging with DevTools
The Chrome DevTools panels, the console, breakpoints and how to read an error.
Updated
What debugging means
Debugging = finding the cause of a bug. The most common mistake: guessing and changing code at random until it "works". The right method is to observe what the code actually does — and the main tool is Chrome DevTools (F12 / ⌥⌘I).
The DevTools panels — what each one does
| Panel | What it helps with |
|---|---|
| Elements | the real DOM and the applied CSS: which rule wins, where it comes from, the box model; you can edit live |
| Console | errors, console.log, running JS in the page's context |
| Sources | the code + breakpoints: you stop execution and inspect the variables |
| Network | every request: status, headers, body, timing, cache, cookies |
| Application | cookies, localStorage, sessionStorage, IndexedDB, service workers |
| Performance | you record an interaction and see what takes time (JS, layout, paint) |
| Lighthouse | an automatic audit: performance, accessibility, SEO |
Plus the React DevTools extension: the component tree, props, state, and the Profiler (which components re-render and why).
The Console — more than console.log
| Method | When |
|---|---|
console.log({ user, cart }) |
with braces — you also see the variable names |
console.table(users) |
an array of objects as a table |
console.error / console.warn |
shown in color, with a stack trace |
console.time('x') / console.timeEnd('x') |
how long a piece of code takes |
console.trace() |
who called the function |
$0 in the console |
the element selected in Elements |
Breakpoints — the tool few people use
Instead of 10 console.logs, you stop the code exactly where you want:
| Kind | How |
|---|---|
| line breakpoint | click the line number in Sources |
debugger; |
written in the code — it stops there while DevTools is open |
| conditional | right click → "Add conditional breakpoint" → id === 42 |
| on an event | Sources → Event Listener Breakpoints → click |
| on a request | "XHR/fetch breakpoints" — stops when a URL is requested |
| on exceptions | "Pause on exceptions" — stops exactly where the error happened |
When it's paused: you see every variable in scope, the call stack (who called whom), and you step forward one step at a time (step over / into / out).
How to read an error
TypeError: Cannot read properties of undefined (reading 'name')
at UserCard (user-card.tsx:12:24)
at renderWithHooks (react-dom.development.js:...)
- The type (
TypeError) and the message: you read.namefrom anundefinedvalue. - The first line from your own code in the stack:
user-card.tsx, line 12, column 24 — that's where you start. - The question: why is this
undefinedhere? — a breakpoint on line 12, look at the values.
The method, in 5 steps
- Reproduce the bug reliably, with clear steps.
- Isolate it: where's the difference between what you expect and what happens? (Network: is the data wrong? Elements: is the CSS different?)
- Form a hypothesis and check it with a breakpoint / log — don't change code at random.
- Fix the cause, not the symptom.
- Write a test so the bug doesn't come back — see Testing.
Summary
- Elements for the DOM and CSS, Network for requests, Application for storage, Sources for breakpoints.
- Breakpoints (including conditional ones and on exceptions) instead of dozens of
console.logs. - Read the error: the type, the message, the first line from your own code.