使用hooks实现react-sortable-tree CRUD:编辑后数据更新问题求助
React-sortable-tree + Hooks 下编辑后数据不更新的核心排查方向
- 第一类高频根因:未遵循不可变数据更新规则,状态引用未变更
react-sortable-tree 对传入的treeDataprop做浅引用依赖判断,只要顶层数组、匹配到的节点对象的内存引用没有变化,哪怕嵌套的属性值被修改了,组件也不会触发重渲染,表现就是编辑完成后界面数据不更新。
错误实现示例:
正确实现参考:// 错误写法:直接修改原state对象后设置原引用 const handleEdit = (nodeId, newVal) => { treeData.forEach(item => { if (item.id === nodeId) item.title = newVal }) // 传入的还是原数组引用,React检测不到状态变化 setTreeData(treeData) }// 正确写法:递归遍历生成全链路新对象引用 const updateTreeData = (nodes, targetId, newVal) => { return nodes.map(node => { if (node.id === targetId) { return { ...node, title: newVal } } if (node.children) { return { ...node, children: updateTreeData(node.children, targetId, newVal) } } return node }) } const handleEdit = (nodeId, newVal) => { // 基于上一次的state生成新的状态树,保证引用变更 setTreeData(prev => updateTreeData(prev, nodeId, newVal)) } - 第二类高频根因:节点定位逻辑失效,更新写偏
若未给SortableTree配置getNodeKey属性,组件默认靠数组索引定位节点。经过拖拽、增删节点操作后,索引对应的实际节点会发生错位,编辑提交时会把新值写到错误的节点上,从观感上判断就是“编辑完数据没更新”。
对应修复方式:- 给每一个树节点分配全局唯一、不随结构变动的id字段
- 给组件配置
getNodeKey={node => node.id},保证节点定位不受树结构变化影响
- 第三类高频根因:闭包捕获旧状态值,更新逻辑拿不到最新数据
自定义编辑弹窗的提交逻辑如果直接依赖组件外层捕获的treeData闭包值,会因为hooks的闭包特性拿到上一次渲染的旧状态,提交后自然无法把最新值合并到正确的状态树里。
对应修复方式:- 所有涉及treeData更新的操作,统一在
setState的回调函数内读取上一次的状态值,规避闭包旧值问题 - 编辑提交时只传入待更新的节点id和最新表单值作为参数,不要把旧的树状态作为依赖传入更新函数
- 所有涉及treeData更新的操作,统一在
内容的提问来源于stack exchange,提问作者Annath Raj
相关产品推荐
相关产品推荐

