🔍 Debugging & Troubleshooting Master Guide

Transform from a bug hunter to a bug terminator with this comprehensive debugging guide!

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.

graph TD A[Bug Discovered] --> B{Can you reproduce it?} B -->|Yes| C[Isolate the Problem] B -->|No| D[Gather More Info] C --> E[Check Error Messages] D --> F[Add Logging] E --> G[Search for Solution] F --> B G --> H{Solution Found?} H -->|Yes| I[Implement Fix] H -->|No| J[Break Down Problem] J --> C I --> K[Test Thoroughly] K --> L{Fixed?} L -->|Yes| M[Document Solution] L -->|No| C style A fill:#e74c3c style M fill:#2ecc71 style B fill:#3498db style H fill:#f39c12

Essential Debugging Tools Arsenal

Just as a carpenter needs the right tools, a developer needs the right debugging arsenal. Here's your complete toolkit:

Chrome DevTools React Developer Tools Query Monitor VS Code Debugger Postman Redux DevTools Lighthouse Network Tab

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"
sequenceDiagram participant React as React App (3000) participant Browser participant WP as WordPress (8000) React->>Browser: Fetch posts Browser->>WP: OPTIONS request (preflight) WP-->>Browser: ❌ No CORS headers Browser-->>React: CORS Error! Note over WP: Add CORS headers React->>Browser: Fetch posts Browser->>WP: OPTIONS request (preflight) WP-->>Browser: ✅ CORS headers present Browser->>WP: GET request WP-->>Browser: JSON data Browser-->>React: Success!

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.
graph LR A[useEffect runs] --> B[Updates state] B --> C[Component re-renders] C --> D[useEffect runs again] D --> A style A fill:#e74c3c style B fill:#e74c3c style C fill:#e74c3c style D fill:#e74c3c

✅ 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:

  1. Are permalinks enabled? (Settings → Permalinks → Post name)
  2. Is REST API enabled? (Check with: yoursite.com/wp-json)
  3. Is .htaccess writable and configured?
  4. Are you using the correct endpoint?
  5. 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:

  1. Filter by XHR/Fetch: See only API calls
  2. Preserve Log: Keep requests when navigating
  3. Throttling: Simulate slow connections
  4. Copy as cURL: Right-click → Copy → Copy as cURL
  5. Response Preview: See formatted JSON
  6. Timing Tab: Analyze request performance
  7. 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!

graph TD A[React DevTools] --> B[Components Tab] A --> C[Profiler Tab] B --> D[Component Tree] B --> E[Props Inspector] B --> F[State Inspector] B --> G[Hooks Inspector] C --> H[Performance Flamegraph] C --> I[Render Timeline] C --> J[Commit Information] D --> K[Search Components] E --> L[Edit Props Live] F --> M[Modify State Live] style A fill:#61dafb style B fill:#3498db style C fill:#e74c3c

🔍 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!

graph TD Start[Bug Found] --> Check1{Can you reproduce it?} Check1 -->|No| Gather[Gather more information] Check1 -->|Yes| Check2{Check console errors?} Check2 --> Check3{Check Network tab?} Check3 --> Check4{Check React DevTools?} Check4 --> Check5{Isolate component?} Check5 --> Check6{Add breakpoints?} Check6 --> Check7{Check state updates?} Check7 --> Check8{Review recent changes?} Check8 --> Solve[Problem Identified] Solve --> Fix[Implement Fix] Fix --> Test[Test Thoroughly] Test --> Document[Document Solution] style Start fill:#e74c3c style Solve fill:#f39c12 style Document fill:#2ecc71

🔍 The Ultimate Debugging Checklist

  1. Reproduce the bug consistently
  2. Check browser console for errors
  3. Inspect Network tab for failed requests
  4. Verify API endpoints are correct
  5. Check CORS headers
  6. Examine React DevTools for state/props
  7. Add strategic console.logs
  8. Use debugger statements
  9. Test in different browsers
  10. Check for race conditions
  11. Review recent Git commits
  12. Validate data types
  13. Check for memory leaks
  14. Test with production build
  15. Clear cache and hard reload