React删除表格行用deleteRow操作DOM还是通过useState更新为最佳实践?
React表格行删除操作最佳实践说明
你当前方案的问题
首先直接给结论:你现在的原生DOM删除方案可以在极简单的场景下临时运行,但完全不符合React最佳实践,后续出现bug的概率极高,不建议继续使用。
核心问题出在React的运行机制上:
- React的UI完全由状态驱动,内部维护了一套虚拟DOM来和真实DOM做diff更新,你手动修改真实DOM之后,React的虚拟DOM并不会感知到这个变化,一旦组件因为其他状态变更、父组件重渲染等原因触发重绘,React会根据当前持有数据重新渲染所有表格行,你之前手动删掉的行会直接恢复,出现UI和实际数据不一致的问题。
- 如果你的表格后续要扩展排序、筛选、分页能力,DOM节点的顺序和索引会和原始数据索引不一致,手动调用
deleteRow(index)非常容易出现删错行的问题,极端情况下甚至会出现前端删的A行,后端请求传了B行的ID,导致误删数据的故障。
推荐的标准实现方案
按照React最佳实践的要求,所有数据驱动的UI变更都应该通过状态更新实现,你的表格场景应该按如下逻辑改造:
- 调用REST API拿到表格数据后,将数据存入
useState钩子:
const [tableData, setTableData] = useState([]) // 接口请求成功后赋值 useEffect(() => { fetchTableApi().then(res => setTableData(res.data)) }, [])
- 渲染表格时直接遍历
tableData生成所有行,每行绑定唯一key(建议用数据ID不要用索引) - 删除按钮的点击逻辑修改为:
- 拿到当前行的唯一ID,触发删除接口请求
- 接口返回成功后,调用
setTableData过滤掉已删除的行:
触发状态更新后React会自动完成DOM的diff更新,删掉对应的行,完全不需要你手动操作DOM。const handleDelete = async (rowId) => { await deleteRowApi(rowId) setTableData(prev => prev.filter(item => item.id !== rowId)) }
补充说明
如果只是做临时的纯UI交互(比如选中行高亮、滚动到指定行等和数据变更无关的操作),你可以用useRef拿到DOM节点后做原生操作,但只要涉及到数据变更对应的UI更新,永远优先走状态更新的流程。
内容的提问来源于stack exchange,提问作者Diego Lope Loyola
相关产品推荐
相关产品推荐

