minop1205 / react-dnd-treeview

A draggable / droppable React-based treeview component. You can use render props to create each node freely.
MIT License
515 stars 69 forks source link

it has performance issue when we drag&drop on a tree with about 500 rows open all #192

Open btnguyen76 opened 1 year ago

btnguyen76 commented 1 year ago

I'm following the doc, everything is working fine. However if we have a tree with about 500 rows openAll, it's very slow (responsive) when we drag&drop Do you have any suggestion on how to improve performance? Thank you!

minop1205 commented 1 year ago

@btnguyen76 I recognize the performance challenges. This issue is a library issue and I will update the library soon to improve it.

At the very least, I can improve it by reducing unnecessary rendering during drag operations.

btnguyen76 commented 1 year ago

yes, When dragging all my custom nodes are keeping re-rendered. Do you know when you are able to improve it by reducing unnecessary rendering during drag operations? Thanks @minop1205

minop1205 commented 1 year ago

The problem is caused where the top level component in the library is re-rendered during a drag operation.

Therefore, a library modification is required to correct the problem. I am currently working on resolving this issue, but have not yet completed the process.

JorisPannekeet commented 1 year ago

@minop1205 Any update about this?

kibertoad commented 9 months ago

@minop1205 Any updates?

jorgedanisc commented 2 months ago

@minop1205 Are you continuing to work on this?

yuri2peter commented 5 days ago

Hey everyone! I've uncovered a way to drastically reduce re-renders for our CustomNodecomponent, and in my project, it's resulted in a significant performance boost !

The key is using useFuncImmutableto make the changing handles immutable, allowing React.memo to work.

Hope this helps you out!

type CustomNodeProps = {
  node: TreeNode;
  depth: number;
  isOpen: boolean;
  onToggle: () => void;
  onClick: () => void;
  onCtrlClick: () => void;
};

function useFuncImmutable<T extends (...args: any[]) => any>(fn: T) {
  const ref = React.useRef(fn);
  ref.current = fn;
  return React.useCallback((...args: any[]) => {
    return ref.current(...args);
  }, [])  as T;
}

export const CustomNodeWrapper: React.FC<CustomNodeProps> = (props) => {
  const onToggle = useFuncImmutable(props.onToggle);
  const onClick = useFuncImmutable(props.onClick);
  const onCtrlClick = useFuncImmutable(props.onCtrlClick);
  return (
    <CustomNodeMemo
      {...props}
      {...{
        onToggle,
        onClick,
        onCtrlClick,
      }}
    />
  );
};