🔍 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