解决 React Antd Tree 组件中 onExpand 和 onSelect 结合使用时展开树收回的问题

概述

在使用 React Antd 的 Tree 组件时,如果同时使用 onExpandonSelect,并且将 expandedKeys 设置为受控状态,可能会遇到选中节点后展开树自动收回的问题。本文将深入分析问题的根源,并提供解决方案。

场景描述

在清空缓存并刷新页面后,直接点击节点展开时不会出现问题。然而,如果先点击小三角图标展开节点,再点击节点文字,展开的树会意外收回。这种情况通常发生在 expandedKeys 被设置为受控状态时。

问题根源分析

Tree 组件代码示例

<Tree
  blockNode
  className="menu_tree"
  defaultExpandedKeys={treeData.length > 0 ? [treeData[0].key] : ["all"]}
  selectedKeys={selectedKeys}
  expandedKeys={expandedKeys}
  onExpand={onExpand}
  onSelect={onSelect}
  autoExpandParent={autoExpandParent}
  treeData={[
    {
      key: "all",
      title: about?.copyright || "",
      children: treeData,
    },
  ]}
/>
onExpand 函数
const onExpand = (newExpandedKeys: React.Key[]) => {
  console.log(newExpandedKeys);
};

newExpandedKeys 的输出格式为 [27, 38, 59],包含当前选中节点的 key 值及其所有父级节点的 key 值。

onSelect 函数
const onSelect = (key: any) => {
  console.log(key);
};

key 的输出结果为 [27],仅为当前节点的 key 值。

问题原因

  1. expandedKeys 的标准格式应包含当前节点及其所有父级节点的 key 值,即 [27, 38, 59] 这种格式。
  2. 虽然初始化渲染时,直接给出子级节点的 key 值(如 [27])也能使展开生效,但这种格式并不标准。
  3. [27, 38, 59][27]交叉出现时,[27] 会导致展开状态失效,从而引发问题。

解决方案

通用方法:findParents
// 递归查找指定节点的父级节点
const findParents = (nodes: any, targetId: number) => {
  let result: any = [];
  for (let node of nodes) {
    if (node.id === targetId) {
      return [node.id]; // 找到目标节点,返回当前节点
    }
    if (node.children) {
      const found: any = findParents(node.children, targetId); // 在子节点中递归查找
      if (found.length > 0) {
        result = [node.id, ...found]; // 找到目标节点,返回当前节点及其父级节点
        break;
      }
    }
  }
  return result;
};
调用 findParents 获取父级节点

根据实际代码结构,调用 findParents 方法获取父级节点,并更新 expandedKeys

useEffect(() => {
  if (filter.dept) {
    let parents = findParents(deptAllData, filter.dept);
    parents.unshift("all");
    setSelectedKeys([filter.dept]);
    setExpandedKeys(parents);
  } else {
    setSelectedKeys(['all']);
    setExpandedKeys(['all']);
  }
}, [filter.dept]);

总结

通过确保 expandedKeys 始终包含当前节点及其所有父级节点的 key 值,可以有效避免在 onExpandonSelect 结合使用时出现的展开树收回问题。使用递归方法 findParents 可以轻松实现这一目标,确保 Tree 组件的展开状态始终受控且稳定。

关键词: React, Ant Design, Tree 组件, onExpand, onSelect, expandedKeys, 受控状态, 递归查找父节点。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐