API Reference
Complete reference for all React Dev Debugger APIs, hooks, and utilities.
Tracked Hooks
useTrackedState
Drop-in replacement for React's useState with automatic state tracking.
function useTrackedState<T>(
initialValue: T | (() => T),
debugLabel?: string
): [T, (value: T | ((prev: T) => T)) => void]
Parameters:
initialValue: Initial state value or lazy initializer functiondebugLabel(optional): Human-readable label for debugging
Returns:
- Tuple of
[state, setState]identical touseState
Example:
const [count, setCount] = useTrackedState(0, 'counter');
const [user, setUser] = useTrackedState(() => loadUser(), 'currentUser');
useTrackedReducer
Drop-in replacement for React's useReducer with action tracking.
function useTrackedReducer<S, A>(
reducer: (state: S, action: A) => S,
initialState: S,
debugLabel?: string
): [S, (action: A) => void]
// With lazy initialization
function useTrackedReducer<S, A, I>(
reducer: (state: S, action: A) => S,
initialArg: I,
init: (arg: I) => S,
debugLabel?: string
): [S, (action: A) => void]
Parameters:
reducer: Pure function that takes state and action, returns new stateinitialStateorinitialArg: Initial state or argument for initializerinit(optional): Lazy initializer functiondebugLabel(optional): Human-readable label
Returns:
- Tuple of
[state, dispatch]identical touseReducer
Example:
const [state, dispatch] = useTrackedReducer(
todoReducer,
[],
'todos'
);
dispatch({ type: 'ADD_TODO', text: 'Learn React' });
useTrackedContext
Track context consumption in components.
function useTrackedContext<T>(
context: React.Context<T>,
debugLabel?: string
): T
Parameters:
context: React Context objectdebugLabel(optional): Human-readable label
Returns:
- Current context value
Example:
const ThemeContext = createContext<Theme>(defaultTheme);
function ThemedButton() {
const theme = useTrackedContext(ThemeContext, 'theme');
return <button style={{ background: theme.primary }}>Click</button>;
}
useWhyDidYouUpdate
Debug hook that logs which props caused a component to re-render.
function useWhyDidYouUpdate(
componentName: string,
props: Record<string, any>
): void
Parameters:
componentName: Name to display in logsprops: Object containing all props to track
Example:
function ExpensiveComponent({ data, filters, onUpdate }) {
useWhyDidYouUpdate('ExpensiveComponent', { data, filters, onUpdate });
// Component logic...
}
Console Output:
[ExpensiveComponent] Props changed:
- data: {...} -> {...}
- filters: {...} -> {...}
useComponentId
Generate a stable unique ID for a component instance.
function useComponentId(prefix?: string): string
Parameters:
prefix(optional): String to prepend to the ID
Returns:
- Stable unique identifier string
Example:
function MyComponent() {
const id = useComponentId('MyComponent');
console.log(id); // "MyComponent_abc123"
}
useRenderTracking
Track render performance for a component.
function useRenderTracking(
componentName: string,
slowThreshold?: number
): RenderMetrics
Parameters:
componentName: Name to display in performance logsslowThreshold(optional): Milliseconds threshold for slow render warning (default: 16ms)
Returns:
- Object containing render metrics:
renderCount: Total number of rendersaverageTime: Average render duration in mslastTime: Most recent render duration in ms
Example:
function DataTable({ data }) {
const metrics = useRenderTracking('DataTable', 20);
useEffect(() => {
if (metrics.lastTime > 20) {
console.warn('Slow render detected!', metrics);
}
}, [metrics]);
return <table>{/* ... */}</table>;
}
Core APIs
StateTracker
Central state tracking system.
class StateTracker {
// Track a state update
trackUpdate(update: StateUpdate): void;
// Get all updates
getUpdates(): StateUpdate[];
// Get updates for a specific component
getComponentUpdates(componentId: string): StateUpdate[];
// Clear all tracked data
clear(): void;
// Subscribe to updates
subscribe(callback: (update: StateUpdate) => void): () => void;
}
// Access the singleton instance
const tracker = getStateTracker();
Example:
const tracker = getStateTracker();
// Subscribe to all updates
const unsubscribe = tracker.subscribe((update) => {
console.log('State updated:', update);
});
// Get all updates
const updates = tracker.getUpdates();
console.log(`Total updates: ${updates.length}`);
// Cleanup
unsubscribe();
Timeline
Manage chronological state history.
class Timeline {
// Get all timeline entries
getEntries(): TimelineEntry[];
// Get entry by index
getEntry(index: number): TimelineEntry | undefined;
// Get current index
getCurrentIndex(): number;
// Clear timeline
clear(): void;
// Subscribe to changes
subscribe(callback: () => void): () => void;
}
const timeline = getTimeline();
Example:
const timeline = getTimeline();
// Get all entries
const entries = timeline.getEntries();
entries.forEach((entry, index) => {
console.log(`${index}: ${entry.label} at ${entry.timestamp}`);
});
// Subscribe to changes
timeline.subscribe(() => {
console.log('Timeline updated!');
});
TimeTravel
Time-travel debugging functionality.
class TimeTravel {
// Jump to a specific point in history
goTo(index: number): void;
// Step backward
stepBack(): void;
// Step forward
stepForward(): void;
// Pause/resume tracking
pause(): void;
resume(): void;
isPaused(): boolean;
// Get current position
getCurrentIndex(): number;
getTotalSteps(): number;
// Check if can move
canStepBack(): boolean;
canStepForward(): boolean;
}
const timeTravel = getTimeTravel();
Example:
const timeTravel = getTimeTravel();
// Go to beginning
timeTravel.goTo(0);
// Step through history
if (timeTravel.canStepForward()) {
timeTravel.stepForward();
}
// Pause tracking temporarily
timeTravel.pause();
// ... do something ...
timeTravel.resume();
DependencyGraph
Component and state relationship graph.
class DependencyGraph {
// Add a component node
addComponent(node: ComponentNode): void;
// Add a state node
addState(node: StateNode): void;
// Add a connection
addEdge(from: string, to: string, type: EdgeType): void;
// Get graph data
getNodes(): Node[];
getEdges(): Edge[];
// Query relationships
getComponentStates(componentId: string): StateNode[];
getStateDependents(stateId: string): ComponentNode[];
// Clear graph
clear(): void;
}
const graph = getDependencyGraph();
Example:
const graph = getDependencyGraph();
// Get all components
const components = graph.getNodes().filter(n => n.type === 'component');
// Find what depends on a state
const dependents = graph.getStateDependents('myState');
console.log('Components using this state:', dependents);
SnapshotStore
Store and manage state snapshots for time-travel.
class SnapshotStore {
// Save a snapshot
save(snapshot: Snapshot): void;
// Get snapshot by index
get(index: number): Snapshot | undefined;
// Get all snapshots
getAll(): Snapshot[];
// Restore a snapshot
restore(index: number): void;
// Export snapshots
export(): string;
// Import snapshots
import(data: string): void;
// Clear all
clear(): void;
}
const store = getSnapshotStore();
Example:
const store = getSnapshotStore();
// Export current history
const json = store.export();
localStorage.setItem('debug-session', json);
// Later: restore the session
const saved = localStorage.getItem('debug-session');
if (saved) {
store.import(saved);
}
// Restore to a specific point
store.restore(5);
Global API
Access the debugger via the global window object:
interface ReactStateDebuggerAPI {
// Time-travel controls
goTo(index: number): void;
stepBack(): void;
stepForward(): void;
// Tracking controls
pause(): void;
resume(): void;
isPaused(): boolean;
// Data access
getUpdates(): StateUpdate[];
getTimeline(): TimelineEntry[];
getGraph(): { nodes: Node[]; edges: Edge[] };
// Export/Import
exportSnapshot(): string;
importSnapshot(data: string): void;
// Utilities
clear(): void;
showPanel(): void;
hidePanel(): void;
}
// Access globally
window.__REACT_STATE_DEBUGGER__
Example:
// In browser console or your code
const api = window.__REACT_STATE_DEBUGGER__;
// Export current session
const snapshot = api.exportSnapshot();
console.log('Snapshot:', snapshot);
// Jump to a specific state
api.goTo(10);
// Clear everything
api.clear();
Utility Functions
deepDiff
Calculate deep differences between two objects.
function deepDiff(
prev: any,
next: any
): DiffResult
Returns:
interface DiffResult {
added: string[]; // Newly added paths
removed: string[]; // Removed paths
changed: Change[]; // Modified paths with values
}
interface Change {
path: string;
prevValue: any;
nextValue: any;
}
Example:
import { deepDiff } from 'react-dev-debugger';
const prev = { name: 'John', age: 30 };
const next = { name: 'John', age: 31, city: 'NYC' };
const diff = deepDiff(prev, next);
// {
// added: ['city'],
// removed: [],
// changed: [{ path: 'age', prevValue: 30, nextValue: 31 }]
// }
formatValue
Format any value for display in the UI.
function formatValue(value: any, maxLength?: number): string
Example:
import { formatValue } from 'react-dev-debugger';
formatValue({ name: 'John' }); // "{ name: 'John' }"
formatValue([1, 2, 3]); // "[1, 2, 3]"
formatValue(null); // "null"
formatValue(undefined); // "undefined"
safeClone
Deep clone any value safely (handles circular references).
function safeClone<T>(value: T): T
Example:
import { safeClone } from 'react-dev-debugger';
const original = { data: [1, 2, 3], nested: { value: 42 } };
const cloned = safeClone(original);
cloned.nested.value = 99;
console.log(original.nested.value); // Still 42
TypeScript Types
All TypeScript type definitions are exported:
import type {
StateUpdate,
ComponentNode,
StateNode,
TimelineEntry,
Snapshot,
DiffResult,
HookType,
ExternalStoreType,
ReactStateDebuggerAPI,
} from 'react-dev-debugger';
Key Types
interface StateUpdate {
id: string;
timestamp: number;
componentName: string;
componentId: string;
hookType: HookType;
prevValue: unknown;
nextValue: unknown;
label?: string;
actionType?: string;
}
interface ComponentNode {
id: string;
name: string;
parentId?: string;
states: StateNode[];
renderCount: number;
lastRenderDuration: number;
averageRenderDuration: number;
}
interface TimelineEntry {
index: number;
update: StateUpdate;
snapshot: Snapshot;
timestamp: number;
}
Environment Detection
The debugger automatically detects the environment:
import { isDevelopment, isBrowser } from 'react-dev-debugger';
if (isDevelopment() && isBrowser()) {
// Debugger is active
}
The debugger is automatically disabled when:
process.env.NODE_ENV === 'production'- Running in a non-browser environment (SSR, Node.js)
Next Steps
- Check out Store Adapters for state library integration
- Learn Performance Tips for optimization
- Explore Advanced Usage for power features