Skip to main content
Learn how to effectively debug React applications using browser DevTools, React DevTools, and other techniques.

Understanding Error Messages

React provides helpful error messages when something goes wrong.

Common Error Types

Caught during build time by your bundler:
Error: Unexpected token
Usually caused by:
  • Missing closing brackets/parentheses
  • Invalid JSX syntax
  • Typos in code
Occur when your app is running:
TypeError: Cannot read property 'map' of undefined
Usually caused by:
  • Accessing undefined values
  • Incorrect prop types
  • Missing dependencies
Code runs but produces incorrect results:
  • State not updating as expected
  • Wrong calculations
  • Incorrect conditional rendering

Browser DevTools

Console Logging

Use console.log() strategically to inspect values:
function App() {
  const [userInput, setUserInput] = useState({
    initialInvestment: 10000,
    annualInvestment: 1200,
    expectedReturn: 6,
    duration: 10,
  });

  function handleChange(inputIdentifier, newValue) {
    console.log('Input changed:', inputIdentifier, newValue); // Debug log
    
    setUserInput((prevUserInput) => {
      const updated = {
        ...prevUserInput,
        [inputIdentifier]: +newValue,
      };
      console.log('Updated state:', updated); // Debug log
      return updated;
    });
  }

  console.log('App rendering with:', userInput); // Track re-renders

  return (
    <>
      <Header />
      <UserInput userInput={userInput} onChange={handleChange} />
      <Results input={userInput} />
    </>
  );
}
Add descriptive labels to your console.logs to easily identify them:
console.log('🔍 Current state:', state);
console.log('✅ Function called with:', args);

Breakpoints

Set breakpoints in browser DevTools to pause execution:
1

Open DevTools

Press F12 or right-click and select “Inspect”
2

Navigate to Sources tab

Find your source files in the file tree
3

Click line number

Set a breakpoint by clicking the line number where you want to pause
4

Inspect variables

When execution pauses, hover over variables or check the Scope panel

Network Tab

Inspect API calls and responses:
  • Check request/response status
  • Verify request headers and payloads
  • Examine response data
  • Identify slow requests

React DevTools

Install React DevTools

Browser extension for Chrome, Firefox, and Edge

Components Tab

Inspect component hierarchy and props:
1

Select a component

Click on any component in the tree
2

Inspect props and state

View current values in the right panel
3

Edit values

Double-click values to test different scenarios
4

Trace updates

Enable “Highlight updates” to see which components re-render

Profiler Tab

Identify performance issues:
  • Record rendering performance
  • Find components that render too often
  • Identify slow renders
  • Analyze component render times

Common Debugging Scenarios

State Not Updating

Problem: Component doesn’t re-render after state change
// Wrong - mutating state directly
const newData = data;
newData.push(item);
setData(newData);
Solution: Create a new reference
// Right - creating new array
setData([...data, item]);

Infinite Render Loop

Problem: Component keeps re-rendering infinitely
// Wrong - calling setter during render
function App() {
  const [count, setCount] = useState(0);
  setCount(count + 1); // Infinite loop!
  return <div>{count}</div>;
}
Solution: Use effects or event handlers
// Right - update in event handler
function App() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Props Not Passing Correctly

// Wrong - typo in prop name
<UserInput userInpt={userInput} onChange={handleChange} />

// Component expecting 'userInput'
function UserInput({ userInput, onChange }) {
  console.log(userInput); // undefined!
}

Invalid Calculations

Results.jsx
export default function Results({ input }) {
  // Debug: Check if input is valid
  console.log('Results received input:', input);
  
  // Validate before calculations
  const inputIsValid = input.duration >= 1;
  
  if (!inputIsValid) {
    return <p className="center">Please enter a duration greater than zero.</p>;
  }
  
  const resultsData = calculateInvestmentResults(input);
  console.log('Calculated results:', resultsData);
  
  return (
    <table id="result">
      {/* Render results */}
    </table>
  );
}

Debugging Strategies

Divide and Conquer

Comment out sections of code to isolate the problem

Rubber Duck Debugging

Explain your code line-by-line to find logical errors

Check the Basics

Verify imports, prop names, and function calls first

Read Error Messages

Error messages often point directly to the problem

Best Practices

Add Helpful Error Messages

function Results({ input }) {
  if (!input) {
    return <p className="error">No input data provided to Results component</p>;
  }
  
  if (input.duration < 1) {
    return <p className="error">Duration must be at least 1 year</p>;
  }
  
  // Rest of component
}

Use Strict Mode

index.jsx
import { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>
);
Strict Mode helps identify potential problems by:
  • Detecting unexpected side effects
  • Warning about deprecated APIs
  • Double-invoking functions to catch bugs

Validate Props

function UserInput({ userInput, onChange }) {
  // Add runtime validation
  if (!userInput || !onChange) {
    console.error('UserInput requires userInput and onChange props');
    return null;
  }
  
  return (
    <section id="user-input">
      {/* Component content */}
    </section>
  );
}

Debugging Tools Checklist

1

Browser Console

Check for error messages and warnings
2

React DevTools

Inspect component props and state
3

Network Tab

Verify API calls and responses
4

Breakpoints

Pause execution to inspect variables
5

Console Logs

Add strategic logs to trace execution flow

Quick Debugging Tips

  1. Check your imports - Missing imports cause common errors
  2. Verify prop names - Typos in prop names are easy to miss
  3. Log component renders - Add console.log at the top to track re-renders
  4. Use React DevTools - Visualize the component tree and state
  5. Read the error stack trace - The line number is usually accurate
  6. Check for missing keys - Lists need unique key props
  7. Validate input types - Type coercion can cause unexpected behavior
  8. Test in isolation - Simplify code to find the minimal failing case

Resources

React DevTools

Official browser extension for debugging React apps

Error Boundaries

Catch and handle errors in component trees

Build docs developers (and LLMs) love