React中使用react-beautiful-dnd实现表格行拖拽后如何保存状态?
解决方案
你当前无法保存拖拽后状态的核心原因有三点:
- 表格行数据完全硬编码在JSX结构中,没有维护在组件状态里,拖拽结束后没有可更新的数据源
- 没有给
DragDropContext组件绑定必须的onDragEnd回调,这个回调是拖拽动作结束后触发状态更新的唯一入口 - 现有代码中
Draggable的index属性从1开始计数,不符合库的规范,会导致重排逻辑计算错误
修改后的完整可运行代码如下:
import { Component } from 'react'; import React from 'react'; import './App.css'; import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'; class App extends Component { // 把表格数据维护到state中 state = { tableData: [ { id: '1', no: 1, firstName: 'Mark', lastName: 'Otto', account: '@mdo' }, { id: '2', no: 2, firstName: 'Jacob', lastName: 'Thornton', account: '@fat' }, { id: '3', no: 3, firstName: 'Larry the Bird', lastName: '', account: '@twitter' }, ] } // 拖拽结束后的处理逻辑 handleDragEnd = (result) => { // 没有目标放置位置时直接返回 if (!result.destination) return; const sourceIndex = result.source.index; const destIndex = result.destination.index; // 拖拽前后位置没有变化直接返回 if (sourceIndex === destIndex) return; // 复制原数组避免直接修改state const newTableData = Array.from(this.state.tableData); // 取出被拖拽的元素 const draggedItem = newTableData.splice(sourceIndex, 1)[0]; // 把拖拽元素插入到目标位置 newTableData.splice(destIndex, 0, draggedItem); // 更新state触发重渲染,就会显示最新的顺序 this.setState({ tableData: newTableData }); } drawTable = () => { return ( <div> {/* 绑定onDragEnd回调 */} <DragDropContext onDragEnd={this.handleDragEnd}> <Droppable droppableId="Table"> {(provided) => ( <table {...provided.droppableProps} ref={provided.innerRef}> {/* 遍历state数据渲染行,不要硬编码 */} {this.state.tableData.map((item, index) => ( <Draggable key={item.id} draggableId={item.id} index={index}> {(provided) => ( <tr ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}> <td>{item.no}</td> <td>{item.firstName}</td> <td>{item.lastName}</td> <td>{item.account}</td> </tr> )} </Draggable> ))} {provided.placeholder} </table> )} </Droppable> </DragDropContext> </div> ); } render = () => { return ( <div> {this.drawTable()} </div> ); } } export default App;
修改后拖拽结束后新的行顺序会自动保存在组件state中,如果需要持久化存储,直接在handleDragEnd方法中拿到最新的newTableData调用后端接口保存即可。
内容的提问来源于stack exchange,提问作者user13974146
相关产品推荐
相关产品推荐

