使用react-sortable-hoc实现拖拽及按key删除元素的正确方法
我来帮你解决这个问题,你的代码里有几个小问题需要修正,尤其是删除逻辑和props传递的部分,下面一步步来调整:
第一步:修正组件的Props传递与类型定义
你的SortableItem组件定义里,onRemove被放在了第二个参数位置,这不符合React组件的props传递规则,应该把它包含在props对象里。另外,你的items是对象数组(每个item有id和link),但之前的value类型定义成了string,得改成对应的对象类型:
// 先定义item的类型,让代码更清晰易维护 type ItemType = { id: number; link: string; }; // 修正SortableItem的props定义 const SortableItem = SortableElement(({ value, onRemove }: { value: ItemType; onRemove: (id: number) => void }) => ( <div className="dragItems" style={{ background: 'gray' }}> <img src={value.link} alt={`item-${value.id}`} /> {/* 点击按钮时直接传递当前item的id */} <button className="dragCloseBtn" onClick={() => onRemove(value.id)}>×</button> </div> ));
第二步:修正SortableList的渲染逻辑
之前的key用了index,但拖拽排序后index会动态变化,建议用item的唯一标识id作为key,这样能保证React组件复用的稳定性。同时要把onRemove函数传递给每个SortableItem:
const SortableList = SortableContainer(({ items, onRemove }: { items: ItemType[]; onRemove: (id: number) => void }) => { return ( <div className="dragAndDrop"> {items.map((value, index) => ( <SortableItem key={`item-${value.id}`} // 用id作为key,避免排序后key不稳定 index={index} value={value} onRemove={onRemove} // 把删除函数传递给子组件 /> ))} </div> ); });
第三步:修正删除函数的逻辑
之前的onRemove试图通过e.target.value获取值,但按钮本身并没有这个属性,这种方式不可靠。我们可以直接接收item的id,然后通过过滤数组的方式删除对应元素(这种方式符合React状态更新的immutable原则,比直接修改原数组更安全):
constructor(props: any) { super(props); this.state = { items: [ { "id": 0, "link": "https://via.placeholder.com/150" }, { "id": 1, "link": "https://via.placeholder.com/150" } ] as ItemType[], // 加上类型断言,让TypeScript识别类型 }; } // 排序函数保持不变,正常工作 public onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => { this.setState({ items: arrayMove(this.state.items, oldIndex, newIndex), }); }; // 修正后的删除函数 public onRemove = (itemId: number) => { // 过滤掉id匹配的元素,返回全新的数组 const updatedItems = this.state.items.filter(item => item.id !== itemId); this.setState({ items: updatedItems }); };
第四步:更新SortableList的调用
现在需要把onRemove函数传递给SortableList,让它能传递给子组件:
<SortableList items={this.state.items} onSortEnd={this.onSortEnd} onRemove={this.onRemove} // 传递删除函数 lockAxis="xy" axis="xy" />
为什么这样调整?
- 用
id作为key:避免拖拽排序后,React因为index变化而错误地复用组件,导致渲染异常。 - 用
filter删除元素:符合React状态更新的immutable原则,不会直接修改原数组,减少意外bug。 - 明确传递
id到删除函数:比通过DOM元素取值更可靠,尤其是在复杂组件结构里不会出错。
这样调整后,你的拖拽排序和删除功能就能正常工作了,点击每个item的关闭按钮时,对应的元素会被删除,同时拖拽排序的功能不受影响。
内容的提问来源于stack exchange,提问作者gomez
相关产品推荐
相关产品推荐

