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: 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
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:
Open DevTools
Press F12 or right-click and select “Inspect”
Navigate to Sources tab
Find your source files in the file tree
Click line number
Set a breakpoint by clicking the line number where you want to pause
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
Install React DevTools Browser extension for Chrome, Firefox, and Edge
Components Tab
Inspect component hierarchy and props:
Select a component
Click on any component in the tree
Inspect props and state
View current values in the right panel
Edit values
Double-click values to test different scenarios
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!
}
function UserInput ( props ) {
console . log ( 'Received props:' , props );
// Check what props were actually received
const { userInput , onChange } = props ;
// Destructure to catch missing props
}
// Fix typo
< UserInput userInput = { userInput } onChange = { handleChange } />
Invalid Calculations
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
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 >
);
}
Browser Console
Check for error messages and warnings
React DevTools
Inspect component props and state
Network Tab
Verify API calls and responses
Breakpoints
Pause execution to inspect variables
Console Logs
Add strategic logs to trace execution flow
Quick Debugging Tips
Check your imports - Missing imports cause common errors
Verify prop names - Typos in prop names are easy to miss
Log component renders - Add console.log at the top to track re-renders
Use React DevTools - Visualize the component tree and state
Read the error stack trace - The line number is usually accurate
Check for missing keys - Lists need unique key props
Validate input types - Type coercion can cause unexpected behavior
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