You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用useSWR实现React树形视图的动态子节点加载与追加

使用useSWR实现树形视图的动态子节点加载方案

核心思路

利用useSWR的缓存机制和手动触发数据更新能力,结合节点唯一标识(如nodeId)管理各节点的子数据,既复用已有缓存,又能精准更新指定父节点的子节点列表。

具体实现步骤

1. 封装API请求函数

假设API端点格式为/api/tree?parentId={parentId}&depth=1(单次仅加载目标节点的下一层子节点),先统一封装请求逻辑:

const fetchTreeChildren = async (parentId) => {
  const res = await fetch(`/api/tree?parentId=${parentId}&depth=1`);
  if (!res.ok) throw new Error('加载子节点失败');
  return res.json(); // 返回父节点的直接子节点数组
};

2. 初始加载前4层数据

直接请求根节点的前4层数据(假设根节点parentId为0):

const { data: initialTree } = useSWR('/api/tree?parentId=0&depth=4', fetchTreeChildren);

3. 动态加载指定节点的子数据

提供两种可行方案,按需选择:

方案一:手动mutate更新全局缓存

在节点展开回调中,先请求子数据,再更新初始树形结构的缓存:

import { useSWR, mutate } from 'swr';

// 点击节点展开时执行
const handleExpand = async (targetNode) => {
  // 生成当前节点的缓存键,避免重复请求
  const childCacheKey = `/api/tree?parentId=${targetNode.id}&depth=1`;
  // 请求并缓存子节点数据
  const newChildren = await mutate(childCacheKey, fetchTreeChildren(targetNode.id), {
    revalidate: false,
    populateCache: true
  });

  // 更新初始树形结构的缓存,追加新子节点
  mutate('/api/tree?parentId=0&depth=4', (prevTree) => {
    // 递归找到目标节点并更新子节点
    const updateNode = (nodes) => nodes.map(node => {
      if (node.id === targetNode.id) {
        return { ...node, children: [...(node.children || []), ...newChildren] };
      }
      return node.children ? { ...node, children: updateNode(node.children) } : node;
    });
    return updateNode(prevTree);
  }, { revalidate: false });
};

方案二:递归组件嵌套useSWR(自动渲染)

如果树形结构通过递归组件渲染,可在每个节点组件中单独使用useSWR,数据返回后自动渲染子节点:

const TreeNode = ({ node }) => {
  const [isExpanded, setIsExpanded] = useState(false);
  // 仅当节点是叶子节点且展开时,才请求子数据
  const { data: children, isLoading } = useSWR(
    isExpanded && node.isLeaf ? `/api/tree?parentId=${node.id}&depth=1` : null,
    fetchTreeChildren
  );

  return (
    <div>
      <div onClick={() => setIsExpanded(prev => !prev)}>
        {node.name} {isLoading && '加载中...'}
      </div>
      {isExpanded && children && (
        <div style={{ marginLeft: 20 }}>
          {children.map(child => <TreeNode key={child.id} node={child} />)}
        </div>
      )}
    </div>
  );
};

这种方式无需手动合并数据,useSWR会自动缓存每个节点的子数据,再次展开时直接读取缓存。

4. 关键注意事项

  • 缓存键唯一性:每个节点的子数据请求需用唯一缓存键(包含parentId),避免缓存冲突。
  • 避免重复请求:利用useSWR的缓存机制,同一节点的子数据仅请求一次。
  • 不可变更新:手动更新树形数据时,需遵循不可变原则,减少不必要的重渲染。

内容的提问来源于stack exchange,提问作者jithu reddy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:40:48