npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-obj-view

v1.1.2

Published

A powerful React component for visualizing JavaScript objects and data structures with an interactive, expandable tree view

Readme

react-obj-view

High-performance React component for inspecting deeply nested objects with virtualization, grouping, and deterministic value getters.

npm bundle size

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.
  • Async Rendering – non-blocking tree traversal keeps the UI responsive even when processing massive datasets.
  • Resolver system – promises, maps, sets, errors, dates, regexes, iterables, grouped proxies, typed arrays, buffers, and custom classes.
  • Sticky path headers – pin ancestor rows while scrolling so nested contexts stay visible.
  • Grouping for huge payloadsarrayGroupSize & objectGroupSize bucket massive collections (objects must be enumerated first—see note below). Groups are collapsed by default to ensure minimal impact on render performance.
  • TypeScript-native – published .d.ts and React 19 JSX runtime support.
  • Zero dependencies – lightweight and self-contained (besides React).
  • Styling hooks – CSS variables + theme presets plus className/style escape hatches.
  • Generic tree APIs – build custom tree views for non-object data structures (files, ASTs, etc.).
  • Copy to clipboard – built-in action buttons to copy primitive values or JSON-serialized objects.
  • Change awareness – optional flashing highlights updated values.
  • Interactive hover – highlights the indentation guide for the current parent context.
  • Line numbers – optional gutter with 0-based indices for debugging.

📦 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. Groups are collapsed by default for performance. 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. Groups are collapsed by default for performance. | | resolver | Map<any, ResolverFn> | undefined | Merge in custom resolvers keyed by constructor. | | highlightUpdate | boolean | false | Flash updated values via useChangeFlashClasses. | | stickyPathHeaders | boolean | true | Pins the current node's ancestor label while you scroll through its children; disable to revert to free-scrolling rows. | | 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. | | actionRenders | React.FC<ObjectViewRenderRowProps> | DefaultActions | Custom component to render row actions (copy, expand, etc.). See example. | | iterateSize | number | 100000 | Controls the number of steps the async walker performs before yielding to the main thread. Lower values improve responsiveness but may increase total render time. |

👉 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" />

Note: The built-in themeDefault adapts automatically to light and dark modes using CSS light-dark() and the user's prefers-color-scheme. Other presets (e.g., One Dark, Dracula, Monokai) are static and do not change automatically. The demo’s light/dark/auto toggle affects the page chrome only — ObjectView does not auto-switch its theme; choose a preset explicitly if you want a specific look.

Want full control? Build your own palette with the exported helpers:

import {
  createTheme,
  extendTheme,
  themeDefault,
} from "react-obj-view";

// Build from scratch (every CSS variable from the table below is required)
const midnight = createTheme({
  "--bigobjview-color": "#e8eaed",
  "--bigobjview-bg-color": "#0b1116",
  "--bigobjview-change-color": "#ff8a65",
  "--bigobjview-fontsize": "12px",
  "--bigobjview-type-boolean-color": "#18ffff",
  "--bigobjview-type-number-color": "#ffab40",
  "--bigobjview-type-bigint-color": "#ff6d00",
  "--bigobjview-type-string-color": "#ffee58",
  "--bigobjview-type-object-array-color": "#40c4ff",
  "--bigobjview-type-object-object-color": "#7e57c2",
  "--bigobjview-type-object-promise-color": "#ec407a",
  "--bigobjview-type-object-map-color": "#00e5ff",
  "--bigobjview-type-object-set-color": "#26c6da",
  "--bigobjview-type-function-color": "#80cbc4",
  "--bigobjview-type-object-regexp-color": "#ef5350",
  "--bigobjview-type-object-date-color": "#8bc34a",
  "--bigobjview-type-object-error-color": "#ff7043",
  "--bigobjview-action-btn": "#444",
  "--bigobjview-action-success": "#00e676",
  "--bigobjview-action-error": "#ff5252",
});

// …or extend an existing preset
const midnightCondensed = extendTheme(midnight, {
  "--bigobjview-fontsize": "11px",
  lineHeight: 12,
});

Refer to the “Styling reference” table in the docs whenever you need the full list of supported CSS variables.

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 the lineHeight prop 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.

Interactive features

Copy to Clipboard

Each row includes built-in action buttons:

// Primitives get a "Copy" button
const config = { apiKey: "sk-abc123", timeout: 5000 };
<ObjectView valueGetter={() => config} />
// Hover over any row to see Copy / Copy JSON buttons

// Copy actions show success/error feedback
// Automatically resets after 5 seconds
  • Copy button for strings, numbers, bigints – copies the raw value
  • Copy JSON button for objects, arrays, dates – serializes via JSON.stringify()

Hover Interactions

The viewer highlights the indentation guide for the current parent context on hover, making it easier to trace parent-child relationships:

<ObjectView valueGetter={() => deeplyNested} expandLevel={3} />
// Hover over any row to see visual feedback
// CSS custom properties (--active-index, --active-parent) enable theme customization

No configuration needed—the feature is built-in and adapts to your theme.

Line Numbers

Enable a gutter with 0-based line numbers for easier debugging:

<ObjectView
  valueGetter={() => largeData}
  showLineNumbers={true}
  lineHeight={18}
/>

Building custom tree views

The library now exports generic tree APIs for non-object data:

import { walkingFactory, type WalkingAdapter } from 'react-obj-view';

// Define your domain (e.g., file system, AST, org chart)
type FileNode = {
  name: string;
  type: 'folder' | 'file';
  children?: FileNode[];
};

// Implement the adapter
const fileAdapter: WalkingAdapter<...> = {
  valueHasChild: (node) => node.type === 'folder' && !!node.children?.length,
  iterateChilds: (node, ctx, ref, cb) => {
    node.children?.forEach(child => cb(child, child.name, { ... }));
  },
  // ... other methods
};

const fileTreeFactory = () => walkingFactory(fileAdapter);

See Generic Tree Stack for a complete walkthrough with React integration.

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:coverage

See 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) | 23.7 ms (42.3 ops/s) | npx vitest bench bench/perf.bench.ts | | react-obj-view | Flatten ~1M-node payload | 253 ms (4.0 ops/s) | npx vitest bench bench/perf.bench.ts | | react-obj-view | Flatten ~2M-node payload | 525 ms (1.9 ops/s) | npx vitest bench bench/perf.bench.ts |

*Measured on macOS (Apple M3 Max, Node 22.11, Vitest 4.0.8). Each sample instantiates a fresh walkingToIndexFactory, generates 10k/100k/200k user records (~100k/~1M/~2M nodes total), and walks the tree. Adjust bench/perf.bench.ts to mirror 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.
  • Generic Tree Stack – explains tree-core, react-tree-view, and the virtual-scroller for building custom viewers.
  • Object Tree Adapter & React Viewer – details how the built-in ObjectView composes the generic stack with resolvers.
  • 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