From 89bf5ddc52ad4892aad3f100b1bb7f4dc4fc8a4f Mon Sep 17 00:00:00 2001 From: nenikola Date: Wed, 27 Mar 2024 00:31:20 +0100 Subject: [PATCH 1/2] fix: iterative approach to getFlattenedTree and getFlattenedTreePaths --- src/selectors/getFlattenedTree.js | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/selectors/getFlattenedTree.js b/src/selectors/getFlattenedTree.js index e59d9a0..2fa2420 100644 --- a/src/selectors/getFlattenedTree.js +++ b/src/selectors/getFlattenedTree.js @@ -1,32 +1,41 @@ export const isNodeExpanded = node => node.state && node.state.expanded; export const nodeHasChildren = node => node.children && node.children.length; -export const getFlattenedTree = (nodes, parents = []) => - nodes.reduce((flattenedTree, node) => { +export const getFlattenedTree = (nodes, parents = []) => { + const flattenedTree = []; + const stack = [...nodes.map(node => ({node, parents}))]; + + while (stack.length > 0) { + const {node, parents} = stack.shift(); const deepness = parents.length; const nodeWithHelpers = {...node, deepness, parents}; if (!nodeHasChildren(node) || !isNodeExpanded(node)) { - return [...flattenedTree, nodeWithHelpers]; + flattenedTree.push(nodeWithHelpers); + } else { + flattenedTree.push(nodeWithHelpers); + stack.unshift(...node.children.map(child => ({node: child, parents: [...parents, node.id]}))); } + } - return [...flattenedTree, nodeWithHelpers, ...getFlattenedTree(node.children, [...parents, node.id])]; - }, []); + return flattenedTree; +}; export const getFlattenedTreePaths = (nodes, parents = []) => { const paths = []; + const stack = [...nodes.map(node => ({node, parents}))]; - for (const node of nodes) { + while (stack.length > 0) { + const {node, parents} = stack.shift(); const {id} = node; if (!nodeHasChildren(node) || !isNodeExpanded(node)) { - paths.push(parents.concat(id)); + paths.push([...parents, id]); } else { - paths.push(parents.concat(id)); - paths.push(...getFlattenedTreePaths(node.children, [...parents, id])); + paths.push([...parents, id]); + stack.unshift(...node.children.map(child => ({node: child, parents: [...parents, id]}))); } } - return paths; }; From ec3286ccad899ba1e48d6b27efb7a39e2dd7c4b4 Mon Sep 17 00:00:00 2001 From: nenikola Date: Wed, 27 Mar 2024 00:32:56 +0100 Subject: [PATCH 2/2] fix: change array.splice to avoid max call stack exceeded with large datasets --- src/state/TreeStateModifiers.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/state/TreeStateModifiers.js b/src/state/TreeStateModifiers.js index ed68512..3adcbb2 100644 --- a/src/state/TreeStateModifiers.js +++ b/src/state/TreeStateModifiers.js @@ -27,7 +27,7 @@ export default class TreeStateModifiers { static editNodeAt = (state, index, nodeUpdate) => { const node = TreeState.getNodeAt(state, index); const updatedNode = typeof nodeUpdate === 'function' ? nodeUpdate(node) : nodeUpdate; - const flattenedTree = [...state.flattenedTree]; + let flattenedTree = [...state.flattenedTree]; const flattenedNodeMap = flattenedTree[index]; const parents = flattenedNodeMap.slice(0, flattenedNodeMap.length - 1); @@ -37,7 +37,11 @@ export default class TreeStateModifiers { if (isNodeExpanded(updatedNode)) { const updatedNodeSubTree = getFlattenedTreePaths([updatedNode], parents); - flattenedTree.splice(index + 1, 0, ...updatedNodeSubTree.slice(1)); + flattenedTree = [ + ...flattenedTree.slice(0, index + 1), + ...updatedNodeSubTree.slice(1), + ...flattenedTree.slice(index + 1 + numberOfVisibleDescendants), + ]; } else { flattenedTree.splice(index + 1, numberOfVisibleDescendants); }