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

如何将framer-motion的Reorder与react-hook-form的useFieldArray联动?

解决framer-motion Reorder与react-hook-form useFieldArray的排序同步问题

问题背景

在ReactJS项目中使用framer-motion的<Reorder>组件实现列表拖拽排序时,无法与react-hook-form的useFieldArray同步表单字段顺序:

  • <Reorder>通过内置逻辑直接修改列表顺序
  • useFieldArray未提供直接修改字段顺序的API,仅支持append/prepend/insert等操作
    尝试过重建字段列表、监听dragStart/dragEnd事件、结合useEffect监听排序变化等方案,均未达到预期效果。

解决方案

核心思路是利用useFieldArray提供的replace方法,在<Reorder>的排序回调中直接将排序后的新数组同步到表单字段,确保fields变量与表单状态实时更新。

完整代码示例

import { useForm, useFieldArray, register } from "react-hook-form";
import { Reorder, ReorderItem } from "framer-motion";

export default function SortableFormList() {
  const { control, handleSubmit } = useForm({
    defaultValues: {
      items: [
        { id: "item-1", content: "第一项" },
        { id: "item-2", content: "第二项" },
        { id: "item-3", content: "第三项" }
      ]
    }
  });

  const { fields, replace } = useFieldArray({
    control,
    name: "items"
  });

  // 处理排序完成后的回调
  const handleReorder = (reorderedItems) => {
    // 使用replace同步排序后的数组到useFieldArray
    replace(reorderedItems);
  };

  const onSubmit = (formData) => {
    console.log("排序后的表单数据:", formData.items);
    // 这里可以提交表单数据到后端
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Reorder.Group axis="y" values={fields} onReorder={handleReorder}>
        {fields.map((item, idx) => (
          <ReorderItem key={item.id} value={item} style={{ padding: "8px", margin: "4px 0", border: "1px solid #eee" }}>
            <input
              {...register(`items.${idx}.content`)}
              defaultValue={item.content}
              style={{ width: "100%" }}
            />
          </ReorderItem>
        ))}
      </Reorder.Group>
      <button type="submit" style={{ marginTop: "16px", padding: "8px 16px" }}>
        提交表单
      </button>
    </form>
  );
}

关键注意事项

  1. 绑定正确的数据源:Reorder.Group的values属性直接传入useFieldArray的fields数组,确保排序操作基于表单字段数据进行。
  2. 使用replace同步数据:onReorder回调返回的reorderedItems是排序后的完整数组,直接传给replace方法,useFieldArray会自动更新fields变量及表单内部状态。
  3. 避免使用index作为key:每个ReorderItem的key必须使用列表项的唯一标识(如item.id),防止排序后因index变化导致React渲染异常。

兼容依赖版本

  • react: ^17.x / ^18.x
  • react-hook-form: ^7.x
  • framer-motion: ^9.x / ^10.x

内容的提问来源于stack exchange,提问作者Pax

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:00:24