From 396e9260154f1c0974b4a31b08e8bb8bbae82602 Mon Sep 17 00:00:00 2001 From: leslielazzarino Date: Fri, 16 Feb 2024 14:13:40 +0100 Subject: [PATCH] Add performance comparison with the 2 most popular react trees on npm - rc-tree - react-accessible-treeview Signed-off-by: leslielazzarino --- package.json | 8 +-- .../RcTreeComparison/RcTreeBasic.tsx | 43 ++++++++++++ .../__tests__/performance.test.tsx | 31 +++++++++ .../ReactAccessibleTreeviewBasic.tsx | 68 +++++++++++++++++++ .../__tests__/performance.test.tsx | 31 +++++++++ 5 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 src/Components/RcTreeComparison/RcTreeBasic.tsx create mode 100644 src/Components/RcTreeComparison/__tests__/performance.test.tsx create mode 100644 src/Components/ReactAccessibleTreeviewComparison/ReactAccessibleTreeviewBasic.tsx create mode 100644 src/Components/ReactAccessibleTreeviewComparison/__tests__/performance.test.tsx diff --git a/package.json b/package.json index 5620dd3..9ab3c5b 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,13 @@ "@mui/icons-material": "^5.11.16", "@mui/material": "^5.12.3", "@mui/system": "^5.11.15", + "ash-tree": "link:./ash-tree/build/", + "rc-tree": "^5.8.5", "react": "^18.2.0", + "react-accessible-treeview": "^2.8.3", "react-dom": "^18.2.0", "react-scripts": "5.0.1", - "ash-tree": "link:./ash-tree/build/", - "web-vitals": "^3.3.2", - "rc-tree": "^5.8.5", - "react-accessible-treeview": "^2.8.3" + "web-vitals": "^3.3.2" }, "devDependencies": { "@testing-library/dom": "^9.3.1", diff --git a/src/Components/RcTreeComparison/RcTreeBasic.tsx b/src/Components/RcTreeComparison/RcTreeBasic.tsx new file mode 100644 index 0000000..b01a94e --- /dev/null +++ b/src/Components/RcTreeComparison/RcTreeBasic.tsx @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: TNG Technology Consulting GmbH +// SPDX-FileCopyrightText: Leslie Lazzarino +// SPDX-FileCopyrightText: Benedikt Richter +// +// SPDX-License-Identifier: Apache-2.0 + +import React, { ReactElement } from 'react'; +import '../../styles.css'; +import { testNodes } from '../shared'; +import Tree from 'rc-tree'; +import { NodesForAshTree } from 'ash-tree'; + +// Main drawbacks of this library found so far: lack of examples, typing really difficult to understand, huge package +// size, unusable default structure (no indentation, no collapsing/expanding) +export function RcTreeBasic(): ReactElement { + const treeData = getTreeData(testNodes); + + return ( +
+

Basic Tree

+ +
+ ); +} + +function getTreeData( + nodes: NodesForAshTree, + path: string = '', + // eslint-disable-next-line @typescript-eslint/no-explicit-any +): any { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const treeData: any = []; + for (const name of Object.keys(nodes)) { + const node = nodes[name]; + treeData.push({ + key: `${path}/${name}`, + title: name ? name : '/', + children: node && node !== 1 ? getTreeData(node) : undefined, + }); + } + + return treeData; +} diff --git a/src/Components/RcTreeComparison/__tests__/performance.test.tsx b/src/Components/RcTreeComparison/__tests__/performance.test.tsx new file mode 100644 index 0000000..5097c73 --- /dev/null +++ b/src/Components/RcTreeComparison/__tests__/performance.test.tsx @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: TNG Technology Consulting GmbH +// SPDX-FileCopyrightText: Leslie Lazzarino +// SPDX-FileCopyrightText: Benedikt Richter +// +// SPDX-License-Identifier: Apache-2.0 + +import React from 'react'; +import { fireEvent, render, screen } from '@testing-library/react'; +import { RcTreeBasic } from '../RcTreeBasic'; + +describe('The BasicTree', () => { + it('takes so long to expand and collapse 100 times', () => { + render(); + + logTimeTakenToExpandAndCollapseRoot100TimesRcTree(); + }); +}); + +export function logTimeTakenToExpandAndCollapseRoot100TimesRcTree(): void { + const startTime = new Date().getTime(); + for (let i = 0; i < 100; i++) { + fireEvent.click(screen.getByText('/')); + fireEvent.click(screen.getByText('/')); + } + const endTime = new Date().getTime(); + console.log( + 'Time taken to render the basic rc tree 100 times: ', + endTime - startTime, + 'ms', + ); +} diff --git a/src/Components/ReactAccessibleTreeviewComparison/ReactAccessibleTreeviewBasic.tsx b/src/Components/ReactAccessibleTreeviewComparison/ReactAccessibleTreeviewBasic.tsx new file mode 100644 index 0000000..a2564c3 --- /dev/null +++ b/src/Components/ReactAccessibleTreeviewComparison/ReactAccessibleTreeviewBasic.tsx @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: TNG Technology Consulting GmbH +// SPDX-FileCopyrightText: Leslie Lazzarino +// SPDX-FileCopyrightText: Benedikt Richter +// +// SPDX-License-Identifier: Apache-2.0 + +import React, { ReactElement } from 'react'; +import '../../styles.css'; +import { testNodes } from '../shared'; +import { NodesForAshTree } from 'ash-tree'; +import TreeView, { INode } from 'react-accessible-treeview'; +import { IFlatMetadata } from 'react-accessible-treeview/dist/TreeView/utils'; + +// Main drawbacks of this library found so far: only one root node allowed +export function ReactAccessibleTreeviewBasic(): ReactElement { + const treeData = getTreeData({ home: testNodes }); + + const nodeRenderer = ({ + element, + getNodeProps, + level, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + handleSelect, // eslint-disable-next-line @typescript-eslint/no-explicit-any + }: any): ReactElement => ( +
+ {element.name} +
+ ); + + return ( +
+

Basic Tree

+ +
+ ); +} + +function getTreeData( + nodes: NodesForAshTree, + parentPath: string | null = null, + treeData: INode[] = [], +): INode[] { + for (const name of Object.keys(nodes)) { + const displayName = name || '/'; + const node = nodes[name]; + const nodePath = `${parentPath || ''}/${displayName}`; + treeData.push({ + id: nodePath, + parent: parentPath, + name: displayName, + children: + node !== 1 + ? Object.keys(node).map( + (childName: string) => `${nodePath}/${childName || '/'}`, + ) + : [], + }); + if (node !== 1) { + getTreeData(node, nodePath, treeData); + } + } + + return treeData; +} diff --git a/src/Components/ReactAccessibleTreeviewComparison/__tests__/performance.test.tsx b/src/Components/ReactAccessibleTreeviewComparison/__tests__/performance.test.tsx new file mode 100644 index 0000000..35346f1 --- /dev/null +++ b/src/Components/ReactAccessibleTreeviewComparison/__tests__/performance.test.tsx @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: TNG Technology Consulting GmbH +// SPDX-FileCopyrightText: Leslie Lazzarino +// SPDX-FileCopyrightText: Benedikt Richter +// +// SPDX-License-Identifier: Apache-2.0 + +import React from 'react'; +import { fireEvent, render, screen } from '@testing-library/react'; +import { ReactAccessibleTreeviewBasic } from '../ReactAccessibleTreeviewBasic'; + +describe('The BasicTree', () => { + it('takes so long to expand and collapse 100 times', () => { + render(); + + logTimeTakenToExpandAndCollapseRoot100TimesRcTree(); + }); +}); + +export function logTimeTakenToExpandAndCollapseRoot100TimesRcTree(): void { + const startTime = new Date().getTime(); + for (let i = 0; i < 100; i++) { + fireEvent.click(screen.getByText('/')); + fireEvent.click(screen.getByText('/')); + } + const endTime = new Date().getTime(); + console.log( + 'Time taken to render the basic rc tree 100 times: ', + endTime - startTime, + 'ms', + ); +}