Package Exports
- react-obj-view
- react-obj-view/dist/react-obj-view.css
Readme
react-obj-view
High-performance React component for inspecting deeply nested objects with virtualization, grouping, and deterministic value getters.
React Object View targets React 19 projects (Node 22+ / Yarn 4 recommended) and ships a TypeScript-first API with ESM + UMD bundles.
✨ Features
- Virtualized tree view – only visible rows render, so 100k+ nodes stay smooth.
- Resolver system – promises, maps, sets, errors, dates, regexes, iterables, grouped proxies, and custom classes.
- Lazy
valueGetter– keeps data fresh without forcing heavy re-renders. - Grouping for huge payloads –
arrayGroupSize&objectGroupSizebucket massive collections (objects must be enumerated first—see note below). - Change awareness – optional flashing highlights updated values.
- Styling hooks – CSS variables + theme presets plus
className/styleescape hatches. - TypeScript-native – published
.d.tsand React 19 JSX runtime support.
📦 Install
npm install react-obj-view
# or
yarn add react-obj-view⚡ Quickstart
import { ObjectView } from "react-obj-view";
import "react-obj-view/dist/react-obj-view.css";
const user = {
name: "Ada",
stack: ["TypeScript", "React"],
meta: new Map([["lastLogin", new Date()]]),
};
export function DebugPanel() {
return (
<ObjectView
valueGetter={() => user}
name="user"
expandLevel={2}
/>
);
}Keep the getter stable
const valueGetter = useCallback(() => user, [user]);
<ObjectView valueGetter={valueGetter} />;Wrap dynamic data in useMemo/useCallback so the virtual tree only re-walks when the underlying value actually changes.
⚙️ Props
| Prop | Type | Default | Description |
|---|---|---|---|
valueGetter |
() => unknown |
required | Lazily supplies the data that should be rendered. |
name |
string |
undefined |
Optional root label shown before the first colon. |
expandLevel |
number | boolean |
false |
Depth of initial expansion; true expands everything (up to depth 20). |
objectGroupSize |
number |
0 |
Enable grouping for objects when they exceed this many keys. Objects must be fully enumerated to detect size, so only enable this when you need grouped previews and can afford the enumeration cost. |
arrayGroupSize |
number |
0 |
Splits very large arrays into range buckets ([0…999]) for faster navigation. |
resolver |
Map<any, ResolverFn> |
undefined |
Merge in custom resolvers keyed by constructor. |
highlightUpdate |
boolean |
false |
Flash updated values via useChangeFlashClasses. |
preview |
boolean |
true |
Show inline previews (Array(5), 'abc…') on collapsed rows. |
nonEnumerable |
boolean |
false |
Include non-enumerable properties during traversal. |
includeSymbols |
boolean |
false |
Include symbol keys when enumerating or previewing objects. |
showLineNumbers |
boolean |
false |
Display a gutter with zero-based line numbers. |
lineHeight |
number |
14 |
Row height (in px) used by the virtual scroller. Keep this in sync with your CSS/fonts; mismatches cause rows to drift/overlap because virtualization still uses the old size. |
style |
React.CSSProperties |
undefined |
Inline styles applied to .big-objview-root (theme presets are plain objects). |
className |
string |
undefined |
Extra class hooked onto .big-objview-root. |
👉 Need more detail? Check the API Documentation.
🎨 Styling & Themes
The package exports several ready-made palettes:
import { ObjectView } from "react-obj-view";
import { themeMonokai } from "react-obj-view";
<ObjectView valueGetter={getter} style={themeMonokai} />;Prefer CSS? Override the variables directly:
.big-objview-root {
--bigobjview-color: #e5e9f0;
--bigobjview-bg-color: #1e1e1e;
--bigobjview-type-string-color: #c3e88d;
--bigobjview-type-number-color: #f78c6c;
}<ObjectView valueGetter={getter} className="object-view" />Line-height tip: If your theme tweaks fonts or padding, expose a shared CSS variable (e.g.
--rov-row-height) and set both.row { height: var(--rov-row-height) }and thelineHeightprop from the same value so scrolling math stays correct.
🧩 Advanced Usage
Custom resolvers
class ApiEndpoint {
constructor(
public method: string,
public url: string,
public status: number,
public responseTime: number,
) {}
}
const resolver = new Map([
[
ApiEndpoint,
(endpoint, cb, next, isPreview) => {
if (isPreview) {
cb('summary', `${endpoint.method} ${endpoint.url}`, true);
cb('status', endpoint.status, true);
return;
}
cb('responseTime', `${endpoint.responseTime}ms`, true);
next(endpoint);
},
],
]);
<ObjectView valueGetter={() => data} resolver={resolver} />;Grouping massive datasets
<ObjectView
valueGetter={() => largeObject}
objectGroupSize={250}
arrayGroupSize={500}
/>- Arrays get chunked up immediately because their length is known.
- Objects must be enumerated to count keys. Use grouping when the trade-off (initial enumeration vs. quicker navigation) makes sense for the payload.
Virtual scrolling reminders
- Always pass the correct
lineHeight(or follow the CSS-variable approach) when changing typography. - The component sets its container height to
lineHeight * size. If you clamp the container via CSS, ensure the scroll parent can actually scroll; otherwise virtualization can’t measure the viewport.
🧪 Testing & Tooling
The repository ships a large Vitest suite (utilities, walkers, resolvers, components, integration scenarios).
npm test # run everything once
npm run test:watch # watch mode
npm run test:ui # launch Vitest UI
npm run test:coverageSee TESTING.md for coverage numbers, structure, and tips.
🚀 Use Cases
- Debug panels – Inspect Redux/Context refs without spamming console logs.
- API/LLM explorers – Visualize nested JSON or streaming responses with circular references.
- State machines & devtools – Pair with hot reloaders or feature flags to watch state change in real time.
- Data-heavy dashboards – Embed next to chart/table widgets so analysts can drill into raw payloads.
📊 Performance Snapshot
| Library | Scenario | Mean time* | Command |
|---|---|---|---|
| react-obj-view | Flatten ~100k-node payload (see bench/perf.bench.ts) |
28.1 ms (35.6 ops/s) | npx vitest bench bench/perf.bench.ts |
*Measured on macOS (Apple M3 Max, Node 22.11, Vitest 4.0.8). The benchmark instantiates a fresh walkingToIndexFactory, generates 10k user records (~100k nodes total), and walks the tree per sample. Adjust bench/perf.bench.ts to match your datasets if you need environment-specific numbers.
Third-party libraries aren’t benchmarked here; run their official examples under the same conditions for apples-to-apples comparisons.
📚 Resources
- Usage Guide – end-to-end patterns, resolver recipes, styling guidance.
- API Documentation – deeper dive into props, hooks, and resolver authoring.
- Live demo – try grouping, previews, and change flashes in the browser.
🧰 Local Development
git clone https://github.com/vothanhdat/react-obj-view
cd react-obj-view
yarn install
yarn dev📜 License
MIT © Vo Thanh Dat