React:防止使用大型树结构重新渲染子对象



我有一个树/目录结构的数据,大约有14k个节点。我想防止树的所有子级重新渲染,因为它需要太长的时间。单击按钮时,可以展开和最小化节点,该按钮将节点的id添加到以Redux状态保存的expandedSet中。当前,将类别添加到"集"时,将重新渲染整个树。我该如何防止这种情况发生?

数据结构:

[
{
"id": "1",
"name": "Category 1",
"children": [
{
"id": "11",
"name": "Category 1-1",
"children": []
}
]
},
{
"id": "2",
"name": "Category 2",
"children": [
{
"id": "3",
"name": "Category 2-1",
"children": [
...children
]
}
]
}
... and so forth
]

我有一个递归TreeTableBranch组件,它递归地呈现它的子级:

const TreeTableBranch: React.FC<Props> = ({
node,
level,
onExpand
}) => {
const expanded = useSelector((state: AppState) => state.categories.expanded);
const shouldExpand = expanded.has(node.category.id);
return (
...lots of divs for rendering a node
<button onClick={onExpand}>Expand<Button/> 
{ shouldExpand &&
node.children.map((v,i) => (
<TreeTableBranch
key={v.category.id}
node={v}
level={level + 1}
onExpand={onExpand}
/>
)}
)
}

但是,由于expanded列表已修改,所有子项都将重新渲染。我尝试使用useMemo()如下:

const children = useMemo(() => {
return (
shouldExpand &&
node.children.map((v, i) => (
<TreeTableBranch
key={`category-branch-${v.category.id}`}
node={v}
level={level + 1}
onExpand={onExpand}
onAddCategory={onAddCategory}
onDeleteCategory={onDeleteCategory}
/>
))
);
}, [shouldExpand]);

但是,这不起作用,可能是因为expanded列表已被修改。

我也试过这样使用React.memo()

const areEqual = (prevProps: Props, nextProps: Props) => {
return prevProps.shouldExpand === nextProps.shouldExpand;
};

但这并不能阻止其他孩子重新渲染。

任何帮助或提示都将不胜感激!

如果不更改树的结构,我无法阻止重新渲染。我已经将树扁平化为一个列表,并确保TreeTableBranch使用React.memo,就像@Sam提到的那样:export default React.memo(TreeTableBranch);没有添加compasion函数及其父函数。我还删除了@glinda93建议的传递onExpandonAddCategoryonDeleteCategory功能道具,尽管我不能100%确定这是否修复了它

最后,我意识到大型树的初始渲染仍然需要很长时间,因此使用这种扁平化的结构,使用react-window虚拟化列表要容易得多。

相关内容

  • 没有找到相关文章

最新更新