Skip to content

Commit

Permalink
refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
afc163 committed Oct 15, 2024
1 parent 02f25e5 commit 92d47ce
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 60 deletions.
38 changes: 17 additions & 21 deletions src/hooks/useFilterTreeData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@ import * as React from 'react';
import type { DefaultOptionType, InternalFieldName, TreeSelectProps } from '../TreeSelect';
import { fillLegacyProps } from '../utils/legacyUtil';

type GetFuncType<T> = T extends boolean ? never : T;
type FilterFn = GetFuncType<TreeSelectProps['filterTreeNode']>;
type FilterFn = NonNullable<TreeSelectProps['filterTreeNode']>;

export default (
const useFilterTreeData = (
treeData: DefaultOptionType[],
searchValue: string,
{
treeNodeFilterProp,
filterTreeNode,
fieldNames,
}: {
options: {
fieldNames: InternalFieldName;
treeNodeFilterProp: string;
filterTreeNode: TreeSelectProps['filterTreeNode'];
},
) => {
const { fieldNames, treeNodeFilterProp, filterTreeNode } = options;
const { children: fieldChildren } = fieldNames;

return React.useMemo(() => {
Expand All @@ -31,24 +27,24 @@ export default (
: (_, dataNode) =>
String(dataNode[treeNodeFilterProp]).toUpperCase().includes(searchValue.toUpperCase());

function dig(list: DefaultOptionType[], keepAll: boolean = false) {
return list.reduce<DefaultOptionType[]>((total, dataNode) => {
const children = dataNode[fieldChildren];
const filterTreeNodes = (nodes: DefaultOptionType[], keepAll = false): DefaultOptionType[] =>
nodes.reduce<DefaultOptionType[]>((filtered, node) => {
const children = node[fieldChildren];
const isMatch = keepAll || filterOptionFunc(searchValue, fillLegacyProps(node));
const filteredChildren = filterTreeNodes(children || [], isMatch);

const match = keepAll || filterOptionFunc(searchValue, fillLegacyProps(dataNode));
const childList = dig(children || [], match);

if (match || childList.length) {
total.push({
...dataNode,
if (isMatch || filteredChildren.length) {
filtered.push({
...node,
isLeaf: undefined,
[fieldChildren]: childList,
[fieldChildren]: filteredChildren,
});
}
return total;
return filtered;
}, []);
}

return dig(treeData);
return filterTreeNodes(treeData);
}, [treeData, searchValue, fieldChildren, treeNodeFilterProp, filterTreeNode]);
};

export default useFilterTreeData;
60 changes: 26 additions & 34 deletions src/hooks/useTreeData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,35 @@ import type { DataNode, SimpleModeConfig } from '../interface';
import { convertChildrenToData } from '../utils/legacyUtil';
import type { DefaultOptionType } from '../TreeSelect';

function parseSimpleTreeData(
treeData: DataNode[],
{ id, pId, rootPId }: SimpleModeConfig,
): DataNode[] {
const keyNodes = {};
const rootNodeList = [];

// Fill in the map
const nodeList = treeData.map(node => {
const clone = { ...node };
const key = clone[id];
keyNodes[key] = clone;
clone.key = clone.key || key;
return clone;
function buildTreeStructure(nodes: DataNode[], config: SimpleModeConfig): DataNode[] {
const { id, pId, rootPId } = config;
const nodeMap = new Map<string, DataNode>();
const rootNodes: DataNode[] = [];

nodes.forEach(node => {
const nodeKey = node[id];
const clonedNode = { ...node, key: node.key || nodeKey };
nodeMap.set(nodeKey, clonedNode);
});

// Connect tree
nodeList.forEach(node => {
nodeMap.forEach(node => {
const parentKey = node[pId];
const parent = keyNodes[parentKey];
const parent = nodeMap.get(parentKey);

// Fill parent
if (parent) {
parent.children = parent.children || [];
parent.children.push(node);
}

// Fill root tree node
if (parentKey === rootPId || (!parent && rootPId === null)) {
rootNodeList.push(node);
} else if (parentKey === rootPId || rootPId === null) {
rootNodes.push(node);
}
});

return rootNodeList;
return rootNodes;
}

/**
* Convert `treeData` or `children` into formatted `treeData`.
* Will not re-calculate if `treeData` or `children` not change.
* `treeData` `children` 转换为格式化的 `treeData`
* 如果 `treeData` `children` 没有变化,则不会重新计算。
*/
export default function useTreeData(
treeData: DataNode[],
Expand All @@ -50,14 +40,16 @@ export default function useTreeData(
): DefaultOptionType[] {
return React.useMemo(() => {
if (treeData) {
return simpleMode
? parseSimpleTreeData(treeData, {
id: 'id',
pId: 'pId',
rootPId: null,
...(simpleMode !== true ? simpleMode : {}),
})
: treeData;
if (simpleMode) {
const config: SimpleModeConfig = {
id: 'id',
pId: 'pId',
rootPId: null,
...(typeof simpleMode === 'object' ? simpleMode : {}),
};
return buildTreeStructure(treeData, config);
}
return treeData;
}

return convertChildrenToData(children);
Expand Down
7 changes: 2 additions & 5 deletions src/utils/valueUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@ export function toArray<T>(value: T | T[]): T[] {

export function fillFieldNames(fieldNames?: FieldNames) {
const { label, value, children } = fieldNames || {};

const mergedValue = value || 'value';

return {
_title: label ? [label] : ['title', 'label'],
value: mergedValue,
key: mergedValue,
value: value || 'value',
key: value || 'value',
children: children || 'children',
};
}
Expand Down

0 comments on commit 92d47ce

Please sign in to comment.