如何使用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
相关产品推荐
相关产品推荐

