The Detective's Mindset: Debugging Philosophy
Debugging is like being Sherlock Holmes in the digital world. Every error is a clue, every console log is evidence, and every stack trace tells a story. The key is not to panic but to investigate systematically.
Essential Debugging Tools Arsenal
Just as a carpenter needs the right tools, a developer needs the right debugging arsenal. Here's your complete toolkit:
Common Error #1: CORS - The Gatekeeper Problem
CORS errors are like a bouncer at a club who won't let you in because you're not on the list. Your React app (from localhost:3000) is trying to talk to WordPress (from localhost:8000), but the browser's security bouncer says "Not on my watch!"
🔴 The Error:
Access to fetch at 'http://localhost:8000/wp-json/wp/v2/posts' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
✅ The Solutions:
// Solution 1: WordPress functions.php
function add_cors_headers() {
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
status_header(200);
exit();
}
}
add_action('init', 'add_cors_headers');
// Solution 2: Use a proxy in package.json (development only)
{
"proxy": "http://localhost:8000"
}
// Solution 3: Use a CORS plugin for WordPress
// Install: "WP CORS" or "WP REST API Controller"
Common Error #2: The Undefined Monster
The "Cannot read property of undefined" error is like trying to open a door that doesn't exist. You're reaching for something that isn't there yet!
🔴 The Error:
TypeError: Cannot read property 'title' of undefined
at PostCard (PostCard.js:15)
at renderWithHooks (react-dom.development.js:14985)
✅ The Solutions:
// Solution 1: Optional Chaining (ES2020)
const title = post?.title?.rendered;
// Solution 2: Conditional Rendering
{post && post.title && (
<h2>{post.title.rendered}</h2>
)}
// Solution 3: Default Props
const PostCard = ({ post = {} }) => {
const { title = { rendered: 'Loading...' } } = post;
return <h2>{title.rendered}</h2>;
};
// Solution 4: Loading State
if (loading) return <Spinner />;
if (!post) return <div>No post found</div>;
return <h2>{post.title.rendered}</h2>;
// Solution 5: Guard Clauses
const getTitle = (post) => {
if (!post) return 'No post';
if (!post.title) return 'Untitled';
return post.title.rendered || 'Untitled';
};
Common Error #3: The Infinite Loop Trap
useEffect infinite loops are like a hamster wheel - your code keeps running and running but never gets anywhere, eventually exhausting your browser!
🔴 The Error:
Warning: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.
✅ The Fix:
// ❌ BAD - Infinite Loop
useEffect(() => {
setCount(count + 1); // This causes re-render, which triggers useEffect again!
});
// ✅ GOOD - With Dependency Array
useEffect(() => {
setCount(count + 1);
}, []); // Empty array = runs once on mount
// ✅ GOOD - Conditional Update
useEffect(() => {
if (shouldUpdate) {
setCount(count + 1);
setShouldUpdate(false);
}
}, [shouldUpdate, count]);
// ✅ GOOD - Using Callback
useEffect(() => {
setCount(prevCount => prevCount + 1);
}, [someDependency]); // Not dependent on count
Common Error #4: WordPress REST API 404
Getting a 404 from WordPress REST API is like showing up at the wrong address - you're looking for something that WordPress doesn't know exists!
🔴 The Error:
GET http://localhost:8000/wp-json/wp/v2/posts 404 (Not Found)
🔍 Diagnostic Checklist:
- Are permalinks enabled? (Settings → Permalinks → Post name)
- Is REST API enabled? (Check with: yoursite.com/wp-json)
- Is .htaccess writable and configured?
- Are you using the correct endpoint?
- Is your custom post type registered with 'show_in_rest' => true?
✅ The Solutions:
// Solution 1: Fix Permalinks
// Go to: WordPress Admin → Settings → Permalinks
// Select "Post name" and Save (this regenerates .htaccess)
// Solution 2: Enable REST for Custom Post Types
register_post_type('products', [
'public' => true,
'show_in_rest' => true, // ← This is crucial!
'rest_base' => 'products', // Optional: custom endpoint
'supports' => ['title', 'editor', 'custom-fields']
]);
// Solution 3: Debug REST API
// Test these URLs in order:
// 1. yoursite.com/wp-json → Should show API index
// 2. yoursite.com/wp-json/wp/v2 → Should show endpoints
// 3. yoursite.com/wp-json/wp/v2/posts → Should show posts
// Solution 4: Check .htaccess
# BEGIN WordPress
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
Common Error #5: State Not Updating
When state doesn't update, it's like pressing an elevator button but the elevator never comes - you're doing something, but React doesn't know it needs to respond!
🔴 The Problem:
// You update state but UI doesn't change
handleClick = () => {
user.name = 'John'; // ❌ Mutating state directly
setUser(user); // React doesn't see this as a change!
}
✅ The Solutions:
// For Objects - Create New Reference
// ❌ Wrong
const updateUser = () => {
user.name = 'John';
setUser(user); // Same reference!
};
// ✅ Correct - Spread Operator
const updateUser = () => {
setUser({
...user,
name: 'John'
});
};
// ✅ Correct - Object.assign
const updateUser = () => {
setUser(Object.assign({}, user, { name: 'John' }));
};
// For Arrays - Create New Array
// ❌ Wrong
const addItem = (item) => {
items.push(item);
setItems(items); // Same reference!
};
// ✅ Correct - Spread
const addItem = (item) => {
setItems([...items, item]);
};
// ✅ Correct - Filter/Map (creates new array)
const removeItem = (id) => {
setItems(items.filter(item => item.id !== id));
};
// For Nested Objects
// ✅ Deep Clone for Nested Updates
const updateNested = () => {
setUser({
...user,
address: {
...user.address,
city: 'New York'
}
});
};
Common Error #6: Mixed Content (HTTPS/HTTP)
Mixed content errors are like trying to use a secure vault but leaving the door wide open - your HTTPS site is loading HTTP resources, breaking the security chain!
🔴 The Error:
Mixed Content: The page at 'https://mysite.com' was loaded over HTTPS, but requested an insecure resource 'http://mysite.com/wp-json/wp/v2/posts'. This request has been blocked; the content must be served over HTTPS.
✅ The Solutions:
// Solution 1: Use Protocol-Relative URLs
const API_URL = '//mysite.com/wp-json/wp/v2';
// Solution 2: Force HTTPS in WordPress
// wp-config.php
define('FORCE_SSL_ADMIN', true);
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
$_SERVER['HTTPS'] = 'on';
}
// Solution 3: Update WordPress URLs
// Settings → General → WordPress Address (URL): https://...
// Settings → General → Site Address (URL): https://...
// Solution 4: Environment-Based URLs
const API_URL = process.env.NODE_ENV === 'production'
? 'https://mysite.com/wp-json/wp/v2'
: 'http://localhost:8000/wp-json/wp/v2';
// Solution 5: .htaccess Redirect
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Debugging Tools Deep Dive
Chrome DevTools Network Tab Mastery
The Network tab is like an X-ray machine for your API calls - you can see everything that's happening under the hood!
🎯 Network Tab Pro Tips:
- Filter by XHR/Fetch: See only API calls
- Preserve Log: Keep requests when navigating
- Throttling: Simulate slow connections
- Copy as cURL: Right-click → Copy → Copy as cURL
- Response Preview: See formatted JSON
- Timing Tab: Analyze request performance
- Initiator: See what triggered the request
React Developer Tools Mastery
React DevTools is like having X-ray vision for your components - you can see props, state, hooks, and the component tree in real-time!
🔍 React DevTools Techniques:
// 1. Finding Performance Issues // Look for components highlighted in yellow/red during renders // 2. Debugging Props // Click component → View props → Edit values live // 3. Hook Dependencies // See which values trigger useEffect re-runs // 4. Component Search // Use the search bar with component names or prop values // 5. Console Integration // Select component → Type $r in console to access it console.log($r.props); // Selected component's props console.log($r.state); // Selected component's state // 6. Debugging Re-renders // Enable "Highlight updates when components render" // Watch for unexpected flashing // 7. Performance Profiling // Start profiling → Interact with app → Stop → Analyze flamegraph
WordPress Debug Mode
WordPress Debug Mode is like turning on all the lights in a dark room - suddenly you can see all the warnings and errors that were hiding!
⚙️ Enable WordPress Debugging:
// wp-config.php - Development Settings
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', true);
define('SCRIPT_DEBUG', true);
define('SAVEQUERIES', true);
// Advanced Debugging
define('WP_DEBUG_LOG', '/path/to/custom/debug.log');
// REST API Debugging
add_filter('rest_pre_echo_response', function($result, $server, $request) {
error_log('REST Request: ' . $request->get_route());
error_log('REST Response: ' . json_encode($result));
return $result;
}, 10, 3);
// Query Monitor Plugin Configuration
// Install Query Monitor plugin for visual debugging
// Shows: Database queries, PHP errors, HTTP requests,
// Hooks & Actions, Block editor blocks, and more!
// Custom Debug Function
function debug_log($message) {
if (WP_DEBUG === true) {
if (is_array($message) || is_object($message)) {
error_log(print_r($message, true));
} else {
error_log($message);
}
}
}
// Usage
debug_log('User ID: ' . get_current_user_id());
debug_log($_POST); // Log entire POST array
Console Debugging Strategies
Console methods are like different types of highlighters - each one helps you mark and find information in different ways!
🎯 Advanced Console Techniques:
// 1. Styled Console Logs
console.log('%c Important Message! ',
'background: #222; color: #bada55; font-size: 16px; padding: 5px;');
// 2. Console Groups
console.group('API Call Details');
console.log('Endpoint:', endpoint);
console.log('Method:', method);
console.log('Headers:', headers);
console.groupEnd();
// 3. Console Table for Arrays/Objects
const users = [
{ name: 'John', age: 30, role: 'Admin' },
{ name: 'Jane', age: 25, role: 'User' }
];
console.table(users);
// 4. Performance Timing
console.time('API Call');
fetch('/api/posts').then(() => {
console.timeEnd('API Call'); // API Call: 245.23ms
});
// 5. Stack Trace
console.trace('Where did this come from?');
// 6. Conditional Logging
console.assert(user.age >= 18, 'User is not an adult!', user);
// 7. Object Deep Inspection
console.dir(document.body, { depth: 2 });
// 8. Count Occurrences
function trackEvent(event) {
console.count(event); // Button Click: 1, Button Click: 2, etc.
}
// 9. Memory Debugging
console.memory; // Check memory usage
// 10. Clear with Style
console.clear();
console.log('%c Console Cleared! ',
'background: red; color: white; font-size: 20px;');
VS Code Debugging Setup
VS Code debugging is like having a time machine for your code - you can pause execution, step through line by line, and inspect everything!
🔧 VS Code Configuration:
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome for React",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/src",
"sourceMapPathOverrides": {
"webpack:///src/*": "${webRoot}/*"
}
},
{
"type": "node",
"request": "launch",
"name": "Debug Node.js",
"program": "${workspaceFolder}/server.js",
"envFile": "${workspaceFolder}/.env"
}
],
"compounds": [
{
"name": "Full Stack",
"configurations": ["Launch Chrome for React", "Debug Node.js"]
}
]
}
// Debugging Shortcuts
// F5: Start Debugging
// F9: Toggle Breakpoint
// F10: Step Over
// F11: Step Into
// Shift+F11: Step Out
// Shift+F5: Stop Debugging
// Conditional Breakpoints (Right-click on line number)
// Expression: user.role === 'admin'
// Hit Count: Break after 5 hits
// Log Message: Log without stopping
// Debug Console Commands
// Watch expressions in real-time
// Evaluate expressions while paused
// Modify variables during execution
Error Boundary Implementation
Error Boundaries are like safety nets for your React app - they catch errors and prevent the entire app from crashing!
🛡️ Error Boundary Component:
// ErrorBoundary.js
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null,
errorCount: 0
};
}
static getDerivedStateFromError(error) {
// Update state so next render shows fallback UI
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// Log error to error reporting service
console.error('Error Boundary Caught:', error, errorInfo);
// Send to error tracking service
if (window.Sentry) {
window.Sentry.captureException(error, {
contexts: { react: { componentStack: errorInfo.componentStack } }
});
}
// Store error details
this.setState({
error,
errorInfo,
errorCount: this.state.errorCount + 1
});
}
handleReset = () => {
this.setState({
hasError: false,
error: null,
errorInfo: null
});
};
render() {
if (this.state.hasError) {
// Fallback UI
return (
<div style={{
padding: '20px',
background: '#fee',
border: '1px solid #fcc',
borderRadius: '5px',
margin: '20px'
}}>
<h2>Oops! Something went wrong 😢</h2>
<details style={{ whiteSpace: 'pre-wrap', marginTop: '10px' }}>
<summary>Click for error details</summary>
<p>{this.state.error && this.state.error.toString()}</p>
<p>{this.state.errorInfo && this.state.errorInfo.componentStack}</p>
</details>
<button onClick={this.handleReset} style={{
marginTop: '10px',
padding: '10px 20px',
background: '#007bff',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer'
}}>
Try Again
</button>
</div>
);
}
return this.props.children;
}
}
// Usage
function App() {
return (
<ErrorBoundary>
<Header />
<ErrorBoundary>
<MainContent />
</ErrorBoundary>
<Footer />
</ErrorBoundary>
);
}
// Custom Hook for Error Handling
function useErrorHandler() {
const [error, setError] = React.useState(null);
const resetError = () => setError(null);
const captureError = React.useCallback((error) => {
setError(error);
console.error('Error captured:', error);
}, []);
React.useEffect(() => {
if (error) throw error;
}, [error]);
return { captureError, resetError };
}
Performance Debugging
Performance issues are like traffic jams in your app - everything slows down and users get frustrated. Let's find and fix the bottlenecks!
⚡ Performance Debugging Tools:
// 1. React Profiler API
import { Profiler } from 'react';
function onRenderCallback(id, phase, actualDuration) {
console.log(`${id} (${phase}) took ${actualDuration}ms`);
}
<Profiler id="PostList" onRender={onRenderCallback}>
<PostList posts={posts} />
</Profiler>
// 2. Performance Observer
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('LCP:', entry.startTime);
}
});
observer.observe({ entryTypes: ['largest-contentful-paint'] });
// 3. Why Did You Render
// npm install @welldone-software/why-did-you-render
import whyDidYouRender from '@welldone-software/why-did-you-render';
if (process.env.NODE_ENV === 'development') {
whyDidYouRender(React, {
trackAllPureComponents: true,
logOwnerReasons: true
});
}
// 4. Custom Performance Hook
function usePerformanceTimer(label) {
React.useEffect(() => {
performance.mark(`${label}-start`);
return () => {
performance.mark(`${label}-end`);
performance.measure(
label,
`${label}-start`,
`${label}-end`
);
const measure = performance.getEntriesByName(label)[0];
console.log(`${label}: ${measure.duration}ms`);
};
}, [label]);
}
Debugging Checklist
When faced with a bug, follow this systematic approach - like a pilot's pre-flight checklist!
🔍 The Ultimate Debugging Checklist
- ☐ Reproduce the bug consistently
- ☐ Check browser console for errors
- ☐ Inspect Network tab for failed requests
- ☐ Verify API endpoints are correct
- ☐ Check CORS headers
- ☐ Examine React DevTools for state/props
- ☐ Add strategic console.logs
- ☐ Use debugger statements
- ☐ Test in different browsers
- ☐ Check for race conditions
- ☐ Review recent Git commits
- ☐ Validate data types
- ☐ Check for memory leaks
- ☐ Test with production build
- ☐ Clear cache and hard reload