π Try it now
A high-performance React JSON diff viewer for large, real-world JSON data.
Built to handle tens of thousands of lines without freezing the UI, it uses virtualized rendering to stay fast and responsive even in production-scale scenarios.
Powered by json-diff-kit, it supports virtual scrolling, advanced comparison options, search, dual minimaps, and customizable theming.
Most JSON diff viewers work well for small examples, but start breaking down in real-world scenarios:
- Large JSON files cause the UI to freeze or crash
- Rendering thousands of DOM nodes makes scrolling unusable
- Array changes are hard to reason about without object-level comparison
- Itβs difficult to understand the impact of changes beyond raw diffs
virtual-react-json-diff was built to solve these problems.
It is designed for internal dashboards and developer tools that need to compare large, deeply nested JSON objects efficiently and interactively.
virtual-react-json-diff is designed for scenarios where traditional diff viewers become unusable due to size or complexity.
- Virtualized rendering powered by
react-window - Smooth scrolling and interaction even with very large diffs
- Dual minimap with visual change indicators
- Jump directly to changes using search highlighting
- Optional single minimap for compact layouts
- Line count statistics for added, removed, and modified lines
- Object-level statistics when using compare-key array diffs
- Quickly assess how big or risky a change really is
- Ignore specific keys or paths anywhere in the JSON tree
- Multiple comparison strategies (
strict,loose,type-aware) - Fine-grained control over how values are considered equal
- Custom class names for theming
- Inline diff customization
- Access raw diff data for advanced use cases
π Try it now - Interactive demo with live examples
npm install virtual-react-json-diff
# or
yarn add virtual-react-json-diff
# or
pnpm add virtual-react-json-diffimport { VirtualDiffViewer } from "virtual-react-json-diff";
const oldData = { name: "Alice", age: 25 };
const newData = { name: "Alice", age: 26, city: "NYC" };
export default function App() {
return (
<VirtualDiffViewer
oldValue={oldData}
newValue={newData}
height={600}
showLineCount={true}
showObjectCountStats={false}
/>
);
}The viewer exposes two different configuration layers, each serving a distinct purpose.
differOptionsβ Controls how the diff is generatedcomparisonOptionsβ Controls what is compared and how values are matched
These options are passed directly to the underlying diff engine.
Use them to:
- Choose how arrays are compared (
compare-key, positional, etc.) - Define comparison keys for object arrays
- Control depth, circular detection, and modification behavior
differOptions={{
arrayDiffMethod: "compare-key",
compareKey: "id",
maxDepth: 999
}}These options affect comparison behavior without changing the diff structure.
Use them to:
- Ignore volatile fields (timestamps, metadata)
- Exclude specific paths
- Compare values across types
comparisonOptions={{
ignoreKeys: ["updatedAt", "__typename"],
ignorePaths: ["meta.timestamp"],
compareStrategy: "type-aware"
}}<VirtualDiffViewer
oldValue={oldData}
newValue={newData}
differOptions={{
arrayDiffMethod: "compare-key",
compareKey: "id"
}}
comparisonOptions={{
ignoreKeys: ["updatedAt"],
compareStrategy: "type-aware"
}}
/>This separation keeps the diff engine flexible while allowing precise control over comparison behavior.
| Prop | Type | Description |
|---|---|---|
oldValue |
object |
Original JSON object (left side). |
newValue |
object |
Updated JSON object (right side). |
| Prop | Type | Default | Description |
|---|---|---|---|
height |
number |
β | Height of the diff viewer in pixels. |
leftTitle |
string |
β | Optional title shown above the left panel. |
rightTitle |
string |
β | Optional title shown above the right panel. |
className |
string |
β | Custom CSS class applied to the root container. |
| Prop | Type | Default | Description |
|---|---|---|---|
hideSearch |
boolean |
false |
Hides the search bar when set to true. |
searchTerm |
string |
"" |
Initial search term to highlight in the diff. |
onSearchMatch |
(index: number) => void |
β | Callback fired when a search match is found. |
showSingleMinimap |
boolean |
false |
Show a single minimap instead of dual minimaps. |
miniMapWidth |
number |
40 |
Width of each minimap in pixels. |
| Prop | Type | Default | Description |
|---|---|---|---|
showLineCount |
boolean |
false |
Display added, removed, and modified line counts. |
showObjectCountStats |
boolean |
false |
Display object-level stats (requires compare-key array diffing). |
Note:
showObjectCountStatsonly works whendifferOptions.arrayDiffMethod = "compare-key"andcompareKeyis provided.
| Prop | Type | Default | Description |
|---|---|---|---|
differOptions |
DifferOptions |
Engine defaults | Controls how the diff is generated (arrays, depth, keys). |
comparisonOptions |
DiffComparisonOptions |
β | Controls what is compared and how values match. |
inlineDiffOptions |
InlineDiffOptions |
{ mode: "char" } |
Fine-tune inline diff rendering behavior. |
| Prop | Type | Default | Description |
|---|---|---|---|
getDiffData |
(diffData: [DiffResult[], DiffResult[]]) => void |
β | Access raw diff results for custom processing or analytics. |
The component exposes a root container with class diff-viewer-container. You can pass your own class name via the className prop to apply custom themes.
Built on top of the awesome json-diff-kit.
MIT Β© Utku AkyΓΌz
Pull requests, suggestions, and issues are welcome!
