You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:14:55