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

React Final Form结合react-beautiful-dnd拖拽时UI出现重复行问题

React Final Form结合react-beautiful-dnd拖拽时UI出现重复行问题

嗨,我刚好碰到过类似的问题,帮你梳理下可能的原因和解决办法~

你提到的情况很典型:拖拽后状态是正确的,但UI却重复了最后一行,这大多是因为React的渲染机制和两个库的交互逻辑没匹配上,具体来说有这几个关键点:

核心原因分析

  1. 不稳定的key值:如果列表项用index作为key,拖拽改变顺序后,React会因为key重复/错乱,误把旧的DOM节点复用成新的行,导致重复渲染。
  2. 拖拽临时元素干扰:react-beautiful-dnd在拖拽过程中会克隆一个临时的拖拽元素,如果这个元素没有被正确区分,FieldArray可能会把它当成列表的一部分渲染。
  3. 表单更新时机不匹配:拖拽结束后更新了数组,但Final Form的FieldArray没有及时感知到变化,还是沿用了旧的渲染快照。

具体解决步骤

1. 给列表项设置唯一且稳定的key

别用索引当key!一定要用每个列表项自身的唯一标识(比如item的id),这样React能精准识别每个元素的变化:

{fields.map((name, index) => {
  const item = fields.value[index];
  // 用item的唯一id作为key,而不是index
  return (
    <Draggable 
      key={item.id} 
      draggableId={item.id.toString()} 
      index={index}
    >
      {(provided) => (
        <div
          ref={provided.innerRef}
          {...provided.draggableProps}
          {...provided.dragHandleProps}
        >
          {/* 你的表单字段内容 */}
          <Field name={`${name}.value`} component="input" />
        </div>
      )}
    </Draggable>
  );
})}

2. 确保拖拽结束后正确更新Final Form的字段数组

不要直接修改state,一定要用FieldArray提供的replace方法来更新数组,这样Final Form会触发正确的重新渲染:

const handleDragEnd = (result) => {
  if (!result.destination) return;

  // 重新排序数组
  const items = Array.from(fields.value);
  const [movedItem] = items.splice(result.source.index, 1);
  items.splice(result.destination.index, 0, movedItem);

  // 用FieldArray的replace方法更新,而不是手动改state
  fields.replace(items);
};

3. 区分拖拽临时元素(可选)

如果还是有问题,可以给拖拽克隆的元素加特殊标识,渲染时跳过它:

<Draggable 
  key={item.id} 
  draggableId={item.id.toString()} 
  index={index}
>
  {(provided, snapshot) => (
    // 只有非拖拽状态的元素才正常渲染表单字段
    <div
      ref={provided.innerRef}
      {...provided.draggableProps}
      {...provided.dragHandleProps}
      style={{
        ...provided.draggableProps.style,
        opacity: snapshot.isDragging ? 0.5 : 1
      }}
    >
      {!snapshot.isDragging && (
        <Field name={`${name}.value`} component="input" />
      )}
    </div>
  )}
</Draggable>

按照这几步调整后,应该就能解决UI重复行的问题了~

备注:内容来源于stack exchange,提问作者shifoc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 10:38:15