react-beautiful-dnd拖拽后,如何将对象数组position设为数组索引?
解决react-beautiful-dnd拖拽后更新元素position属性的问题
核心要注意保持数组的不可变性,同时在重排后遍历新数组,给每个元素的position赋值当前索引。以下是完整实现步骤和代码示例:
1. 拖拽逻辑与position更新结合
假设你的characters是用useState管理的状态:
import { useState } from 'react'; import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'; function DragList() { const [characters, setCharacters] = useState([ { id: '1', name: 'A', position: 0 }, { id: '2', name: 'B', position: 1 }, { id: '3', name: 'C', position: 2 }, ]); const handleOnDragEnd = (result) => { // 无有效拖拽目标或位置未变化时直接返回 if (!result.destination || result.source.index === result.destination.index) return; // 1. 复制原数组,避免直接修改原状态 const newCharacters = Array.from(characters); // 2. 执行拖拽重排逻辑 const [draggedItem] = newCharacters.splice(result.source.index, 1); newCharacters.splice(result.destination.index, 0, draggedItem); // 3. 遍历新数组,更新每个元素的position为当前索引 const updatedCharacters = newCharacters.map((item, index) => ({ ...item, position: index, })); // 4. 更新状态 setCharacters(updatedCharacters); }; return ( <DragDropContext onDragEnd={handleOnDragEnd}> <Droppable droppableId="characters"> {(provided) => ( <div {...provided.droppableProps} ref={provided.innerRef}> {characters.map((item, index) => ( <Draggable key={item.id} draggableId={item.id} index={index}> {(provided) => ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} > {item.name} - position: {item.position} </div> )} </Draggable> ))} {provided.placeholder} </div> )} </Droppable> </DragDropContext> ); } export default DragList;
2. 原for循环失效的常见原因
大概率是以下两种情况:
- 直接修改原数组(比如
characters[i].position = i),React无法检测到状态变化,因为数组引用未改变; - 循环后未重新设置状态,或设置的仍是原数组的引用。
用Array.from复制数组,再通过map生成新的元素对象(保持不可变性),最后更新状态,既能让React感知到变化,也能确保每个元素的position正确对应数组索引。
内容的提问来源于stack exchange,提问作者Megakrash
相关产品推荐
相关产品推荐

