Performance Optimization
Learn how to optimize React Dev Debugger for better performance in large applications.
Best Practices
1. Limit Snapshot History
Control the number of snapshots stored in memory:
import { getSnapshotStore } from 'react-dev-debugger';
const store = getSnapshotStore();
// Configure max snapshots (default: 100)
store.setMaxSnapshots(50);
For adapters:
createReduxAdapter(store, {
maxSnapshots: 50,
});
2. Filter Frequent Updates
Skip tracking high-frequency state updates:
import { getStateTracker } from 'react-dev-debugger';
const tracker = getStateTracker();
// Add a filter
tracker.setFilter((update) => {
// Skip mouse position updates
if (update.label === 'mousePosition') return false;
// Skip animation frame updates
if (update.componentName === 'AnimationController') return false;
return true;
});
3. Use Debug Labels Wisely
Meaningful labels help, but don't overdo it:
// ✅ Good
const [user, setUser] = useTrackedState(null, 'currentUser');
const [cart, setCart] = useTrackedState([], 'shoppingCart');
// ❌ Too verbose
const [x, setX] = useTrackedState(0, 'mousePositionXCoordinate');
4. Disable in Production
The debugger automatically disables in production, but you can force it:
// Only import in development
if (process.env.NODE_ENV === 'development') {
import('react-dev-debugger/dev');
}
5. Selective Component Tracking
Only track specific components:
function ExpensiveComponent({ data }) {
// Only track in development
if (process.env.NODE_ENV === 'development') {
useRenderTracking('ExpensiveComponent');
}
return <div>{/* ... */}</div>;
}
Performance Monitoring
Track Slow Renders
Use the built-in performance tracking:
import { useRenderTracking } from 'react-dev-debugger';
function DataTable({ data }) {
const metrics = useRenderTracking('DataTable', 16); // 16ms threshold
useEffect(() => {
if (metrics.lastTime > 16) {
console.warn('Slow render detected:', metrics);
}
}, [metrics]);
return <table>{/* ... */}</table>;
}
Identify Unnecessary Re-renders
import { useWhyDidYouUpdate } from 'react-dev-debugger';
function OptimizedComponent(props) {
useWhyDidYouUpdate('OptimizedComponent', props);
// Check console for which props changed
return <div>{/* ... */}</div>;
}
Memory Management
Clear Old Data
Periodically clear snapshot history:
import { getSnapshotStore, getTimeline } from 'react-dev-debugger';
// Clear all history
function clearDebugHistory() {
getSnapshotStore().clear();
getTimeline().clear();
}
// Clear automatically after 1000 updates
let updateCount = 0;
tracker.subscribe(() => {
updateCount++;
if (updateCount > 1000) {
clearDebugHistory();
updateCount = 0;
}
});
Throttle Updates
For high-frequency updates, use throttling:
import { throttle } from 'lodash';
function MouseTracker() {
const [position, setPosition] = useTrackedState({ x: 0, y: 0 }, 'mouse');
// Throttle updates to 100ms
const updatePosition = throttle((x, y) => {
setPosition({ x, y });
}, 100);
return (
<div onMouseMove={(e) => updatePosition(e.clientX, e.clientY)}>
{/* ... */}
</div>
);
}
Bundle Size Optimization
Code Splitting
Only load the debugger when needed:
// Lazy load debugger
const loadDebugger = async () => {
if (process.env.NODE_ENV === 'development') {
await import('react-dev-debugger/dev');
}
};
// Load on demand
document.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.shiftKey && e.key === 'D') {
loadDebugger();
}
});
Tree Shaking
Ensure your bundler can tree-shake unused features:
// Only import what you need
import { useTrackedState } from 'react-dev-debugger';
// Instead of
import * as Debugger from 'react-dev-debugger';
Adapter-Specific Optimization
Redux
createReduxAdapter(store, {
// Filter frequent actions
actionFilter: (action) => {
const ignored = ['@@redux/INIT', 'persist/'];
return !ignored.some(prefix => action.type.startsWith(prefix));
},
// Simplify large state
stateTransform: (state) => ({
user: state.user.id,
items: state.items.length,
// ... simplified version
}),
});
Zustand
createZustandAdapter(useStore, {
// Only track specific slices
trackSlices: ['user', 'cart'],
maxSnapshots: 30,
});
Production Considerations
Disable Completely
Remove debugger from production builds:
// webpack.config.js
module.exports = {
resolve: {
alias: {
'react-dev-debugger':
process.env.NODE_ENV === 'production'
? 'react-dev-debugger/noop'
: 'react-dev-debugger',
},
},
};
Environment Variables
# .env.development
REACT_APP_ENABLE_DEBUGGER=true
# .env.production
REACT_APP_ENABLE_DEBUGGER=false
if (process.env.REACT_APP_ENABLE_DEBUGGER === 'true') {
import('react-dev-debugger/dev');
}
Benchmarking
Measure Impact
const start = performance.now();
// Your code with debugger
const [state, setState] = useTrackedState(0, 'counter');
const end = performance.now();
console.log(`Hook overhead: ${end - start}ms`);
Compare Performance
// Without debugger
const baseline = measureRenderTime(ComponentWithoutDebugger);
// With debugger
const withDebugger = measureRenderTime(ComponentWithDebugger);
console.log(`Overhead: ${withDebugger - baseline}ms`);
Tips for Large Applications
- Use Selective Tracking - Only track critical state
- Limit History - Set reasonable maxSnapshots
- Filter Noise - Skip frequent, unimportant updates
- Clear Regularly - Don't let history grow indefinitely
- Lazy Load - Only activate debugger when needed
- Monitor Memory - Watch browser DevTools memory tab
Performance Checklist
- maxSnapshots configured appropriately
- Filters set up for noisy updates
- Debug labels are concise
- Production builds exclude debugger
- Large state objects are transformed
- High-frequency updates are throttled
- Memory usage is monitored
- Only critical components tracked