useCallback/useMemo with array



我的应用程序内部性能有问题。原因是我正在使用带有大量 deps 的 useCallback,如下所示

const getTreeData = React.useCallback((tree: Area.Model[]): TreeItem[] => {
let treeData: TreeItem[] = [];
if (tree) {
treeData = {
flatData: tree.map(
(area): any => {
const areaKey = getKeyForArea(area.id, area.type, area.closestGroupId);
return {
id: area.id,
name: area.name,
type: area.type,
title: (
<TreeTitle
id={area.id}
key={area.id}
type={area.type}
title={area.name}
closestGroupId={area.closestGroupId}
expandable={area.drillableDirections !== undefined && area.drillableDirections.includes(Drill.Direction.DOWN)}
status={status[areaKey]}
counter={subAreas[areaKey]}
unselectedStoreCounter={unselectedStoreCounter[areaKey]}
onAggregationButtonClick={handleAggregateOptionToggle}
onQuickAggregationOptionForSubGroups={handleQuickAggregateOptionForSubGroupsToggle}
onQuickAggregationOptionForSubStores={handleQuickAggregateOptionForSubStoresToggle}
/>
),
parent: area.closestGroupId,
expanded: status[areaKey].isExpanded,
};
},
),
getKey: (node: any): number => node.id,
getParentKey: (node: any): number => node.parent || 0,
rootKey: 0,
};
}
return treeData;
}, [status, subAreas, unselectedStoreCounter, handleAggregateOptionToggle, handleQuickAggregateOptionForSubGroupsToggle, handleQuickAggregateOptionForSubStoresToggle]);

如您所见,代码中使用了所有依赖项。但是,每次有更改时,只会有 1 个元素更新,但整个函数会重新运行并返回一个全新的对象,这将在另一个地方触发我的渲染函数。

因此,我的问题是:有没有办法让我使用useCallbackuseMemo来优化此代码?

我认为性能问题的根本原因是您安装了太多的dom元素。我对此有同样的问题,并通过虚拟化树解决了它。我为此使用了反应虚拟化树,这是它是如何进行的。

虚拟化树.js

import React from 'react';
import PropTypes from 'prop-types';
import Tree from 'react-virtualized-tree/lib/Tree';
import TreeStateModifiers from 'react-virtualized-tree/lib/state/TreeStateModifiers'
import { UPDATE_TYPE } from 'react-virtualized-tree/lib/contants'
import { Node } from 'react-virtualized-tree/lib/shapes/nodeShapes';
export default class UnstableFastTree extends React.Component {
static contextTypes = {
unfilteredNodes: PropTypes.arrayOf(PropTypes.shape(Node))
};
get nodes() {
return this.context.unfilteredNodes || this.props.nodes;
}
handleChange = ({ node, type, index }) => {
let nodes;
if (type === UPDATE_TYPE.UPDATE) {
nodes = TreeStateModifiers.editNodeAt(this.props.nodes, index, node);
} else {
nodes = TreeStateModifiers.deleteNodeAt(this.props.nodes, index);
}
this.props.onChange(nodes);
};
render() {
return (
<Tree
nodeMarginLeft={this.props.nodeMarginLeft}
nodes={this.props.nodes}
onChange={this.handleChange}
NodeRenderer={this.props.children}
/>
);
}
}
UnstableFastTree.propTypes = {
extensions: PropTypes.shape({
updateTypeHandlers: PropTypes.object
}),
nodes: PropTypes.shape({
flattenedTree: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.oneOf([PropTypes.number, PropTypes.string])))
.isRequired,
tree: PropTypes.arrayOf(PropTypes.shape(Node)).isRequired
}),
onChange: PropTypes.func,
children: PropTypes.func.isRequired,
nodeMarginLeft: PropTypes.number,
width: PropTypes.number,
scrollToId: PropTypes.number
};
UnstableFastTree.defaultProps = {
nodeMarginLeft: 30
};

树.js

import React, { useMemo } from 'react'
import PropTypes from 'prop-types'
import pick from 'lodash/pick'
import VirtualizedTree from '@controls/VirtualizedTree'
import TreeState from 'react-virtualized-tree/lib/state/TreeState'
import TreeNode from './TreeNode'
export default function BrowseTree(props) {
const {
treeData
} = props
const getAllNodes = all => all.reduce((acc, el) => [
...acc,
el,
...(el.collapse ? getAllNodes(el.children) : [])
], [])
const nodes = useMemo(() => TreeState.createFromTree(treeData), [treeData])
const treeProps = pick(props, [
'type', 'selectedNodeId', 'onNodeClick', 'onHideDialog', 'onShowDialog',
'browseToggle', 'disableIds', 'config', 'fetching', 'topicIcon', 'role'
])
return (
<VirtualizedTree nodes={nodes}>
{({ style, node }) => (
<TreeNode
key={node.db_id}
style={style}
node={node}
{...treeProps}
/>
)}
</VirtualizedTree>
)
}
BrowseTree.propTypes = {
type: PropTypes.string.isRequired,
treeData: PropTypes.array.isRequired
}

我希望这有所帮助。

相关内容

  • 没有找到相关文章

最新更新