Skip to main content

Advanced Features

Explore powerful advanced features of React Dev Debugger for complex debugging scenarios.

Custom State Tracking

Manual State Registration

Track state from any source:

import { getStateTracker } from 'react-dev-debugger';

const tracker = getStateTracker();

// Track custom state update
tracker.trackUpdate({
id: generateId(),
timestamp: Date.now(),
componentName: 'CustomComponent',
componentId: 'custom-1',
hookType: 'custom',
prevValue: oldValue,
nextValue: newValue,
label: 'customState',
renderCycleId: getRenderCycleId(),
});

Integration with Custom Libraries

class CustomStateManager {
constructor() {
this.listeners = [];
this.tracker = getStateTracker();
}

setState(newState) {
const prevState = this.state;
this.state = newState;

// Track the change
this.tracker.trackUpdate({
// ... update details
});

this.listeners.forEach(fn => fn(newState));
}
}

Snapshot Management

Export/Import Sessions

Save and restore debugging sessions:

import { getSnapshotStore } from 'react-dev-debugger';

const store = getSnapshotStore();

// Export current session
function saveSession() {
const data = store.export();
localStorage.setItem('debug-session', data);
// or download as file
downloadJSON(data, 'debug-session.json');
}

// Restore session
function loadSession() {
const data = localStorage.getItem('debug-session');
if (data) {
store.import(data);
}
}

Share Sessions with Team

// Share via URL
function shareSession() {
const snapshot = store.export();
const compressed = compressString(snapshot);
const url = `${window.location.origin}?debug=${compressed}`;
navigator.clipboard.writeText(url);
}

// Load from URL
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const debugData = params.get('debug');
if (debugData) {
const decompressed = decompressString(debugData);
store.import(decompressed);
}
}, []);

Advanced Time-Travel

Conditional Time-Travel

import { getTimeTravel } from 'react-dev-debugger';

const timeTravel = getTimeTravel();

// Jump to first error state
function goToFirstError() {
const timeline = getTimeline().getEntries();
const errorIndex = timeline.findIndex(entry =>
entry.update.label === 'error'
);
if (errorIndex !== -1) {
timeTravel.goTo(errorIndex);
}
}

// Find state by value
function findState(predicate) {
const entries = getTimeline().getEntries();
const index = entries.findIndex(entry =>
predicate(entry.snapshot.state)
);
if (index !== -1) {
timeTravel.goTo(index);
}
}

Replay Mode

class ReplayController {
constructor() {
this.timeTravel = getTimeTravel();
this.isPlaying = false;
this.speed = 1000; // ms per step
}

play() {
this.isPlaying = true;
this.playNext();
}

playNext() {
if (!this.isPlaying) return;

if (this.timeTravel.canStepForward()) {
this.timeTravel.stepForward();
setTimeout(() => this.playNext(), this.speed);
} else {
this.stop();
}
}

stop() {
this.isPlaying = false;
}

setSpeed(ms) {
this.speed = ms;
}
}

Graph Analysis

Query Dependencies

import { getDependencyGraph } from 'react-dev-debugger';

const graph = getDependencyGraph();

// Find all components using a specific state
function findStateConsumers(stateId) {
const edges = graph.getEdges();
return edges
.filter(edge => edge.from === stateId)
.map(edge => graph.getNode(edge.to));
}

// Find circular dependencies
function findCircularDeps() {
const visited = new Set();
const recursionStack = new Set();

function hasCycle(nodeId) {
visited.add(nodeId);
recursionStack.add(nodeId);

const edges = graph.getEdges().filter(e => e.from === nodeId);
for (const edge of edges) {
if (!visited.has(edge.to)) {
if (hasCycle(edge.to)) return true;
} else if (recursionStack.has(edge.to)) {
return true;
}
}

recursionStack.delete(nodeId);
return false;
}

return graph.getNodes().some(node => hasCycle(node.id));
}

Component Hierarchy

// Build component tree
function buildComponentTree() {
const components = graph.getNodes().filter(n => n.type === 'component');

const tree = {};
components.forEach(comp => {
if (!comp.parentId) {
tree[comp.id] = buildSubtree(comp.id);
}
});

return tree;
}

function buildSubtree(parentId) {
const children = graph
.getNodes()
.filter(n => n.parentId === parentId);

return {
...graph.getNode(parentId),
children: children.map(child => buildSubtree(child.id)),
};
}

Custom Visualizations

Create Custom Views

import { useEffect, useState } from 'react';
import { getStateTracker } from 'react-dev-debugger';

function CustomDebugView() {
const [updates, setUpdates] = useState([]);

useEffect(() => {
const tracker = getStateTracker();
const unsubscribe = tracker.subscribe((update) => {
setUpdates(prev => [...prev, update]);
});
return unsubscribe;
}, []);

// Custom visualization logic
return (
<div>
<h2>Custom Debug View</h2>
{updates.map(update => (
<CustomUpdateCard key={update.id} update={update} />
))}
</div>
);
}

D3.js Integration

import * as d3 from 'd3';
import { getDependencyGraph } from 'react-dev-debugger';

function GraphVisualization() {
const svgRef = useRef();

useEffect(() => {
const graph = getDependencyGraph();
const nodes = graph.getNodes();
const edges = graph.getEdges();

// D3 force simulation
const simulation = d3.forceSimulation(nodes)
.force('link', d3.forceLink(edges).id(d => d.id))
.force('charge', d3.forceManyBody().strength(-300))
.force('center', d3.forceCenter(400, 300));

// Render with D3
const svg = d3.select(svgRef.current);

// ... D3 rendering code
}, []);

return <svg ref={svgRef} width={800} height={600} />;
}

Performance Profiling

Advanced Metrics

import { getRenderTracker } from 'react-dev-debugger';

const renderTracker = getRenderTracker();

// Get detailed metrics
function getPerformanceReport() {
const components = renderTracker.getAllComponents();

return components.map(comp => ({
name: comp.name,
totalRenders: comp.renderCount,
avgDuration: comp.averageRenderDuration,
maxDuration: comp.maxRenderDuration,
minDuration: comp.minRenderDuration,
totalTime: comp.totalRenderTime,
slowRenders: comp.slowRenderCount,
}))
.sort((a, b) => b.totalTime - a.totalTime);
}

// Identify bottlenecks
function findBottlenecks(threshold = 16) {
return getPerformanceReport()
.filter(comp => comp.avgDuration > threshold);
}

Flamegraph Data

// Generate flamegraph-compatible data
function generateFlamegraphData() {
const tracker = getRenderTracker();
const timeline = getTimeline().getEntries();

return timeline.map(entry => ({
name: entry.update.componentName,
value: entry.renderDuration,
timestamp: entry.timestamp,
}));
}

Testing Integration

Snapshot Testing

import { getSnapshotStore } from 'react-dev-debugger';

describe('State Management', () => {
it('should match state snapshot', () => {
const store = getSnapshotStore();
const snapshot = store.get(store.getAll().length - 1);
expect(snapshot).toMatchSnapshot();
});
});

Deterministic Replay

// Record test session
beforeAll(() => {
recordSession();
});

afterAll(() => {
const session = stopRecording();
saveSessionToFile(session);
});

// Replay in tests
it('should reproduce bug', () => {
const session = loadSessionFromFile();
replaySession(session);

// Assert expected state
expect(getAppState()).toBe(expectedState);
});

Plugin System

Create Custom Plugins

class DebugPlugin {
constructor(name, options) {
this.name = name;
this.options = options;
this.tracker = getStateTracker();
}

init() {
this.unsubscribe = this.tracker.subscribe(this.onUpdate.bind(this));
}

onUpdate(update) {
// Plugin logic
}

destroy() {
this.unsubscribe?.();
}
}

// Usage
const plugin = new DebugPlugin('MyPlugin', { /* options */ });
plugin.init();

Logger Plugin Example

class LoggerPlugin extends DebugPlugin {
onUpdate(update) {
console.group(`[${update.componentName}] ${update.label}`);
console.log('Previous:', update.prevValue);
console.log('Next:', update.nextValue);
console.groupEnd();
}
}

WebSocket Sync

Remote Debugging

import { getStateTracker } from 'react-dev-debugger';

class RemoteDebugger {
constructor(wsUrl) {
this.ws = new WebSocket(wsUrl);
this.tracker = getStateTracker();
this.setupSync();
}

setupSync() {
this.tracker.subscribe((update) => {
this.ws.send(JSON.stringify({
type: 'STATE_UPDATE',
data: update,
}));
});

this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'TIME_TRAVEL') {
getTimeTravel().goTo(message.index);
}
};
}
}

Next Steps