Debugging Tips
Master the essential tools and techniques for finding and fixing bugs in your code quickly and efficiently.
What You'll Learn
- Using console.log effectively
- Browser DevTools essentials
- Reading stack traces
- Debugging React components
- Step-by-step debugging process
- Common debugging strategies
The Debugging Mindset
What is Debugging?
Debugging is the process of finding and fixing errors (bugs) in your code. It's a normal part of development—even experienced developers spend significant time debugging!
The Golden Rule
Change one thing at a time, then test.
If you change multiple things, you won't know which change fixed (or broke) something.
Console.log Debugging
Basic Usage
The simplest and most common debugging tool:
console.log('Value:', someVariable);
Strategic Placement
Check if code runs:
function handleClick() {
console.log('Button clicked!'); // Does this run?
// ... rest of function
}
Check variable values:
const [count, setCount] = useState(0);
function increment() {
console.log('Before:', count); // What's the current value?
setCount(count + 1);
console.log('After:', count); // Did it change?
}
Check function inputs:
function greet(name: string) {
console.log('Received name:', name); // What was passed in?
return `Hello, ${name}`;
}
Check data flow:
useEffect(() => {
console.log('Effect running');
console.log('User data:', user);
}, [user]);
Advanced Console Methods
Table view for arrays/objects:
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
];
console.table(users); // Displays as formatted table
Grouping logs:
console.group('User Login Process');
console.log('Step 1: Validate input');
console.log('Step 2: Check credentials');
console.log('Step 3: Create session');
console.groupEnd();
Warnings and errors:
console.warn('This feature is deprecated'); // Yellow warning
console.error('Failed to save data'); // Red error
Object inspection:
const user = { name: 'Alice', settings: { theme: 'dark' } };
console.log('User:', user); // Click to expand in console
console.dir(user); // Shows object structure
Console.log Best Practices
1. Use descriptive labels:
// ❌ Bad
console.log(data);
// ✅ Good
console.log('API Response:', data);
2. Log multiple values:
console.log('Count:', count, 'Total:', total, 'Average:', average);
3. Use objects for clarity:
// ✅ Great for multiple values
console.log({ count, total, average });
4. Remove before committing:
# Search for console.logs before committing
git diff | grep console.log
Browser DevTools
Opening DevTools
- Mac:
Cmd + Option + I - Windows:
F12orCtrl + Shift + I
Console Tab
View all logs:
- All console.log output appears here
- Click to expand objects
- Filter by type (errors, warnings, logs)
Try code live:
// Type directly in console:
document.querySelector('h1').textContent = 'New Title';
Elements Tab
Inspect HTML:
- Click element inspector icon (top-left)
- Hover over page elements
- Click to select
- View HTML structure
Live CSS editing:
- Select element
- Edit styles in right panel
- Changes apply instantly
- Copy working CSS
Check computed styles:
- See final CSS values after all rules applied
- Useful for debugging specificity issues
Network Tab
Monitor API requests:
- Open Network tab
- Reload page or trigger action
- See all requests/responses
Check request details:
Headers: Request method, status code
Preview: Formatted response data
Response: Raw response
Timing: How long request took
Debug failed requests:
- Red = failed (4xx, 5xx errors)
- Click to see error details
- Check Headers tab for status code
Sources Tab
Set breakpoints:
- Find file in left panel
- Click line number to add breakpoint
- Code pauses when line runs
- Inspect variables at that moment
Step through code:
- Step over: Next line
- Step into: Enter function
- Step out: Exit function
- Resume: Continue execution
React DevTools
Install extension:
- Chrome: React Developer Tools
- Firefox: React Developer Tools
Components tab:
- View component tree
- See props and state
- Edit values live
- See re-renders
Profiler tab:
- Measure component performance
- Find slow renders
- Optimize re-renders
Reading Stack Traces
What is a Stack Trace?
Shows the path code took before error:
Error: Cannot read property 'name' of undefined
at UserProfile (UserProfile.tsx:15)
at div
at App (App.tsx:25)
How to Read It
Bottom-to-top flow:
App.tsx:25- App component calledUserProfile.tsx:15- UserProfile component called- Error happened here - Line 15 of UserProfile.tsx
Find the problem:
- Start at the top (where error occurred)
- Look at file name and line number
- Open file and go to that line
- Check what could be undefined
Example
TypeError: Cannot read property 'email' of undefined
at ContactForm (ContactForm.tsx:42)
What to check:
// Line 42 in ContactForm.tsx
<input value={user.email} /> // user is undefined!
// Fix: Check if user exists
<input value={user?.email || ''} />
Debugging React Components
Component Not Rendering
Check 1: Is it imported?
// ❌ Missing import
export default function Page() {
return <Header />; // Error: Header is not defined
}
// ✅ With import
import Header from '@/components/layout/Header';
Check 2: Is it exported?
// ❌ Not exported
function Button() {
return <button>Click</button>;
}
// ✅ Exported
export default function Button() {
return <button>Click</button>;
}
Check 3: Is path correct?
// Check exact file location
import Button from '@/components/ui/Button'; // Must match actual path
Props Not Working
Check parent is passing them:
// Parent
<Card title="Test" /> // ✅ Passing title
// Child
interface CardProps {
title: string;
}
export default function Card({ title }: CardProps) {
console.log('Received title:', title); // Check value
return <h3>{title}</h3>;
}
Check prop names match:
// ❌ Mismatch
<Card title="Test" />
function Card({ name }: { name: string }) { // Looking for 'name' not 'title'
// ✅ Match
<Card title="Test" />
function Card({ title }: { title: string }) {
State Not Updating
Check setter is called:
const [count, setCount] = useState(0);
function increment() {
console.log('Before:', count);
setCount(count + 1); // Is this line running?
console.log('After:', count); // Won't show new value yet!
}
State updates are async:
// ❌ Won't work as expected
setCount(count + 1);
console.log(count); // Still shows old value!
// ✅ Use effect to see updates
useEffect(() => {
console.log('Count changed to:', count);
}, [count]);
Check dependencies:
useEffect(() => {
console.log('User:', user);
}, [user]); // Only runs when 'user' changes
Step-by-Step Debugging Process
When Something Breaks
1. Read the error message:
Don't panic! Read the full error.
Note: file name, line number, error type
2. Find the line:
// Open the file
// Go to the line number
// Look at what's on that line
3. Add console.logs:
// Above the error line
console.log('Before error, variable is:', someVariable);
4. Check values:
Are variables what you expect?
Is something undefined/null?
Is data the right type?
5. Google the error:
Copy error message
Search: "react [error message]"
Check Stack Overflow, GitHub issues
6. Try a fix:
Make ONE change
Test
If it works, understand why
If not, undo and try something else
Common Debugging Strategies
Binary Search
Cut code in half to find problem:
function processData() {
console.log('Step 1'); // Works
const data = fetchData();
console.log('Step 2'); // Works
const cleaned = cleanData(data);
console.log('Step 3'); // Doesn't run - error in cleanData!
return cleaned;
}
Rubber Duck Debugging
Explain code line-by-line:
Talk through code to yourself (or a rubber duck):
- "This function receives user data..."
- "Then it checks if email exists..."
- "Oh! What if email is undefined?" ← Often find the bug!
Comment Out Code
Isolate the problem:
function handleSubmit() {
validateInput(); // Works
// sendToAPI(); // Commenting this out - does error go away?
// updateUI(); // If yes, problem is in one of these
}
Check Assumptions
Question everything:
// Assumption: user is always defined
<p>{user.name}</p>
// Reality: user might be null on first render
// Fix:
<p>{user?.name || 'Loading...'}</p>
Simplify
Reduce to minimal example:
// Complex (hard to debug):
<Card user={users.find(u => u.id === selectedId)} />
// Simplified (easier):
const selectedUser = users.find(u => u.id === selectedId);
console.log('Selected user:', selectedUser);
<Card user={selectedUser} />
Debugging Checklist
When stuck, go through this list:
- Did I save the file?
- Did I refresh the browser?
- Are there errors in the console?
- Did I check the Network tab (for API issues)?
- Did I add console.logs?
- Did I read the full error message?
- Did I check the file and line number?
- Is the component imported correctly?
- Are props being passed correctly?
- Did I check for typos?
- Did I Google the error?
- Did I try hard refresh (Cmd/Ctrl + Shift + R)?
- Did I restart the dev server?
Pro Tips
1. Keep DevTools Open
Always have console open while developing—catch errors immediately.
2. Test Incrementally
Don't write 50 lines then test. Write 5, test, repeat.
3. Use Git to Undo
# See what you changed
git diff
# Undo all changes
git checkout .
# Undo specific file
git checkout -- path/to/file.tsx
4. Create Minimal Reproductions
If stuck, create smallest possible example that shows the bug.
5. Take Breaks
Seriously! Often the solution appears after stepping away.
Quick Reference
Console methods:
console.log() // General logging
console.error() // Errors (red)
console.warn() // Warnings (yellow)
console.table() // Arrays as table
console.dir() // Object structure
DevTools shortcuts:
Cmd/Ctrl + Option/Shift + I - Open DevTools
Cmd/Ctrl + Shift + C - Inspect element
Cmd/Ctrl + Shift + R - Hard refresh
React DevTools:
Components tab - View props/state
Profiler tab - Performance
Debugging process:
1. Read error
2. Find line
3. Add console.logs
4. Check values
5. Google error
6. Try fix
What's Next
Now you know how to debug issues. Learn when to ask for help: