Large tree
This controlled tree has 21,110 nodes: 10 roots, each with 10 children, 100 grandchildren and 2,000 leaves. Check Item 1 to select its 2,000 leaves at once.
Selected leaves: 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9
Item 10
Show code
LargeTreeExample.tsx
import { useState } from 'react';
import TreeSelect, { getSelectedIDs } from '@attebyte/react-tree-select';
import { ExampleNode, generateTree } from './data';
// 10 roots, 100 children, 1,000 grandchildren and 20,000 leaves: 21,110 nodes.
// Selecting a node only re-renders the nodes whose state changed.
export default function LargeTreeExample() {
const [data, setData] = useState<ExampleNode[]>(() => generateTree([10, 10, 10, 20]));
const selectedCount = getSelectedIDs(data, {
uniqueIDProperty: 'value',
childrenProperty: 'children',
valueProperty: 'included',
mode: 'leaves'
}).length;
return (
<div>
<p className='mb-2'>Selected leaves: {selectedCount.toLocaleString()}</p>
<div className='max-h-96 overflow-auto'>
<TreeSelect<ExampleNode>
data={data}
onChange={setData}
uniqueIDProperty='value'
labelProperty='label'
childrenProperty='children'
valueProperty='included'
aria-label='Large tree'
/>
</div>
</div>
);
}
Why it stays fast
- A selection change copies only the changed nodes and their ancestors. Every other node keeps its identity.
- Nodes are memoized, so unchanged nodes don't re-render, and collapsed branches aren't rendered at all.
- Expansion and focus state are tracked per node, so expanding one node doesn't re-render the others.
TreeSelect renders every node in an expanded branch. If you need to show tens of thousands of nodes expanded at the same time, consider virtualizing the list.