mui-x icon indicating copy to clipboard operation
mui-x copied to clipboard

[tree view] Add virtualization support

Open rashdeva opened this issue 5 years ago • 10 comments

Tree View doesn't support virtualization for long-list items. It will be nice to have this feature.

Summary 💡

To maintain consistency with Autocomplete, it's better to use react-window as a virtualization library. To keep the current API, the Tree View component should merge items to flat list and by using indents present items. (https://material-ui.com/components/lists/#nested-list)

Motivation 🔦

Most of the time tree view uses for long lists and structured data. If the parent item has 1000 children, the performance slows down.

Other requests

  • https://docs.google.com/spreadsheets/d/1jJBwkKY1a8a30usE_mvK0dRt86OIhSn89GQ8HZ48ZuI/edit?gid=1226571167#gid=1226571167&range=B3

Benchmarks

  • https://github.com/lukasbach/react-complex-tree
  • https://github.com/brimdata/react-arborist. Project maintained? https://github.com/brimdata/react-arborist/issues/275
  • https://github.com/Lodin/react-vtree no longer maintained
  • https://github.com/ChilliCream/react-aspen no longer maintained
  • https://github.com/diogofcunha/react-virtualized-tree no longer maintained

rashdeva avatar May 08 '20 11:05 rashdeva

Hey @oliviertassinari, is there any news on when this would be implemented? :)

harrycollin avatar Aug 24 '21 14:08 harrycollin

@oliviertassinari Using the DataGridPro with Tree Data solves the performance issue for very large trees? Is this the way?

david-ic3 avatar Feb 14 '22 08:02 david-ic3

Any update about having virtualization in Treeview?

naxis18 avatar Jul 15 '22 09:07 naxis18

Any update about having virtualization in Treeview?

davidpenso avatar Feb 24 '23 10:02 davidpenso

@naxis18 were you able to find a solution for this

davidpenso avatar Feb 24 '23 10:02 davidpenso

Just bumping this as it would be most beneficial for us, too!

CHE1RON avatar Jul 05 '23 11:07 CHE1RON

Using the DataGridPro with Tree Data solves the performance issue for very large trees?

@david-ic3 the data grid could indeed be used this way, and solve the performance issue with large tree. However, https://mui.com/x/react-data-grid/tree-data/ implements the role="treegrid" which isn't the same as role="treeview":

  • treegrid: https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/
  • treeview: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/

So for a tree view like the VS Code file browser, this would have its limits (I don't know each enough to say what are the true differences).


I have transferred this issue to MUI X, per https://mui.com/material-ui/discover-more/roadmap/.

oliviertassinari avatar Jul 15 '23 16:07 oliviertassinari

Waiting for an official implementation, I attempted to implement a tree view with virtualization using react-virtualized-auto-sizer and react-window. The data model is flat, and the depth is determined by a property (depth). The React components are Material-UI components. If anyone is interested, you can find it here: src/component/common/tree-view

MpStyle avatar Feb 25 '24 10:02 MpStyle

Since the virtualization support is already on the MUI X public roadmap with a label Plan: Pro, should we expect that virtualization will be available for the Pro version only?

sauron918 avatar Oct 27 '24 22:10 sauron918

should we expect that virtualization will be available for the Pro version only?

@sauron918 Correct. Per our research (see issue description benchmark), the range of options available is slim, too often those efforts get abandoned. The dream is to bring the amazing VS Code tree view to React. See https://www.reddit.com/r/reactjs/comments/16vt1vv/react_component_needed_virtual_trees_w_drag_and/ for an interesting thread on this.

So it seems that if we license this MIT, we won't be able to make it work long-term (not enough donations, sponsoring, ad revenue, etc.). So we need a commercial license. I think this was borderline to land under the Premium plan (close to no open-source alternatives) but Pro feels less greedy, so more "right".

oliviertassinari avatar Oct 27 '24 22:10 oliviertassinari

Hello, I just wanted to ask if there any estimation to publish data for the virtual-tree at the pro plan? :)

itayG98 avatar Nov 18 '24 13:11 itayG98

@itayG98 We are aiming for an initial release of the virtualization in @mui/x-tree-view-pro for the launch of MUI X v8.0.0, probably in March 2025. The feature might be ready sooner as part of the v8 beta.

See https://mui.com/blog/mui-x-v8-alpha-zero/.

flaviendelangle avatar Nov 18 '24 13:11 flaviendelangle

@itayG98 We are aiming for an initial release of the virtualization in @mui/x-tree-view-pro for the launch of MUI X v8.0.0, probably in March 2025. The feature might be ready sooner as part of the v8 beta.

Would really love to see this as soon as possible!

hazelraidoninc avatar Nov 19 '24 20:11 hazelraidoninc

@itayG98 We are aiming for an initial release of the virtualization in @mui/x-tree-view-pro for the launch of MUI X v8.0.0, probably in March 2025. The feature might be ready sooner as part of the v8 beta.

Great ! I wish you luck!

itayG98 avatar Nov 25 '24 08:11 itayG98

Hello! Thank you @flaviendelangle for the work you have been providing on this feature! Do you have an idea if this is still on track to maybe be introduced in March 2025? If you don't think so, do you have another estimate to share?

Thank you very much for all!

YassineElbouchaibi avatar Mar 01 '25 15:03 YassineElbouchaibi

Hi,

We have some issues around this feature, we won't be able to launch it in March, but hopefully we should be able to resume the work on it soon. Sorry for the delay!

flaviendelangle avatar Mar 03 '25 07:03 flaviendelangle

We are very interested in this. We have to stick with Arborist just for the virtualization.

httpete-broadcom avatar Mar 17 '25 18:03 httpete-broadcom

I built myself a virtualization hook for the TreeView. In my case, the app is wrapped in a Box with an ID of ROOT_APP_CONTAINER_ID - You might want to change the document.querySelector to be the document body.

useVirtualization.ts

import { ROOT_APP_CONTAINER_ID } from "@/app/[language]/RootLayoutClientProviders";
import { useState, useEffect, useCallback } from "react";

export const useVirtualization = <T extends HTMLElement>(): [((node: T | null) => void), boolean] => {
    const [node, setNode] = useState<T | null>(null);
    const [isVisible, setIsVisible] = useState<boolean>(false);
    
    // This callback ref will be called every time the node changes.
    const ref = useCallback((node: T | null) => {
        setNode(node);
    }, []);
    
    useEffect(() => {
        if (!node) return;
        
        const container = document.querySelector(`#${ROOT_APP_CONTAINER_ID}`);
        const observer = new IntersectionObserver(
            (entries) => {
                entries.forEach((entry) => {
                    setIsVisible(entry.isIntersecting);
                });
            },
            {
                root: container,
                threshold: 0,
                rootMargin: "100px",
            }
        );
        
        observer.observe(node);
        
        return () => {
            observer.disconnect();
        };
    }, [node]); // re-run this effect any time the node changes
    
    return [ref, isVisible];
};

DataTreeItem.tsx

export const DataTreeItem = forwardRef(function CustomTreeItem(
    props: CustomTreeItemProps,
    ref: Ref<HTMLLIElement>,
) {
    // ...
    const {
        children,
        // ...
    } = props;

    const [virtualRef, isVisible] = useVirtualization<HTMLLIElement>();
    
    // Merge the forwarded ref with the virtualization ref.
    const setRefs = mergeRefs(ref, virtualRef);
    
    const {
        getContentProps,
        // ...
    } = useTreeItem2({
        // ...
        rootRef: setRefs,
    });

    return (
        <TreeItem2Provider itemId={itemId}>
            <TreeItem2Root {...getRootProps(other)} ref={setRefs}>
                <TreeItem2Content
                    {...getContentProps()}
                    sx={{ height: "51.42px" }}
                >
                    {isVisible && (
                        // Render virtualized content here, i.e. 
                    )}
                </TreeItem2Content>
                {children && <TreeItem2GroupTransition {...getGroupTransitionProps()} />}
            </TreeItem2Root>
        </TreeItem2Provider>
    );
};

roland-rocely avatar Mar 26 '25 15:03 roland-rocely

We are also very interested in this feature. Any idea when it will be arriving? @flaviendelangle. I see that Lazy loading is in the docs but not virtualization. Will virtualization come in v.8?

fellan1996 avatar Apr 16 '25 10:04 fellan1996

The work on the virtualization has been halted due to other priorities. But we should resume it soon and release it in one of the v8 minor releases.

flaviendelangle avatar Apr 16 '25 11:04 flaviendelangle