A performant tree view React component built on top of [react-virtualized](https://bvaughn.github.io/react-virtualized/#/components/List).
npm install @innobrix/react-virtualized-tree
bash
npm install @innobrix/react-virtualized-tree
`
or
`bash
yarn add @innobrix/react-virtualized-tree
`
$3
This library requires the following peer dependencies:
`bash
npm install react react-dom react-virtualized
`
$3
Import the required styles:
`javascript
import 'react-virtualized/styles.css';
`
For the default icon renderers, also import Material Icons:
`javascript
import 'material-icons/css/material-icons.css';
`
Usage
$3
`tsx
import { Tree, TreeState, TreeStateModifiers } from '@innobrix/react-virtualized-tree';
import type { Node, RendererProps } from '@innobrix/react-virtualized-tree';
const nodes: Node[] = [
{
id: 1,
name: 'Parent',
state: { expanded: true },
children: [
{ id: 2, name: 'Child 1' },
{ id: 3, name: 'Child 2' },
],
},
];
function MyTree() {
const [treeNodes, setTreeNodes] = useState(nodes);
return (
{({ node, ...rest }: RendererProps) => (
{node.name}
)}
);
}
`
$3
`tsx
import { Tree, FilteringContainer } from '@innobrix/react-virtualized-tree';
function FilterableTree() {
const [nodes, setNodes] = useState(initialNodes);
return (
{({ nodes: filteredNodes }) => (
{({ node }) => {node.name}}
)}
);
}
`
$3
The library provides several built-in renderers:
`tsx
import { renderers } from '@innobrix/react-virtualized-tree';
const { Expandable, Deletable, Favorite } = renderers;
`
API
$3
`typescript
import {
Tree, // Main tree component
FilteringContainer, // Container for filtering functionality
TreeState, // Tree state management
TreeStateModifiers, // State modification utilities
selectors, // Node selection utilities
renderers, // Built-in renderers (Expandable, Deletable, Favorite)
constants, // Constants (UPDATE_TYPE, etc.)
debounce, // Debounce utility
} from '@innobrix/react-virtualized-tree';
`
$3
`typescript
import type {
Node,
NodeId,
NodeState,
FlattenedNode,
NodeAction,
RendererProps,
TreeProps,
TreeContainerProps,
FilteringContainerProps,
Extensions,
UpdateType,
} from '@innobrix/react-virtualized-tree';
`
$3
| Prop | Type | Description |
|------|------|-------------|
| nodes | Node[] | Array of tree nodes |
| onChange | (nodes: Node[]) => void | Callback when nodes change |
| children | ComponentType | Node renderer component |
| nodeMarginLeft | number | Left margin for nested nodes (default: 25) |
| width | number | Tree width |
| scrollToId | NodeId | ID of node to scroll to |
| scrollToAlignment | string | Scroll alignment |
| onScrollComplete | () => void | Callback when scroll completes |
| extensions | Extensions | Custom update type handlers |
$3
`typescript
interface Node {
id: NodeId; // Unique identifier (number or string)
name: string; // Display name
state?: NodeState; // Node state (expanded, deletable, favorite, etc.)
children?: Node[]; // Child nodes
}
interface NodeState {
expanded?: boolean;
deletable?: boolean;
favorite?: boolean;
[key: string]: unknown; // Custom state properties
}
`
Performance
For optimal performance, memoize your node tree before passing it to the Tree component. This prevents unnecessary re-renders and tree flattening calculations.
$3
`typescript
import { createSelector } from '@reduxjs/toolkit';
const selectRawNodes = (state: RootState) => state.tree.nodes;
// Memoized selector - tree only recalculates when nodes actually change
export const selectNodes = createSelector(
[selectRawNodes],
(nodes) => nodes
);
`
$3
`tsx
import { useMemo } from 'react';
function MyTree({ data }) {
// Memoize the nodes array
const nodes = useMemo(() => transformToNodes(data), [data]);
return (
{({ node }) => {node.name}}
);
}
`
Without memoization, the tree will re-flatten on every parent render, which can be expensive for large trees.
Development
`bash
Install dependencies
npm install
Run development server
npm run dev
Run tests
npm test
Run tests in watch mode
npm run test:watch
Type check
npm run typecheck
Build
npm run build
Lint
npm run lint
``