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

React Hook Form中useFieldArray跨字段数组操作时数据临时丢失问题排查与解决

React Hook Form中useFieldArray跨字段数组操作时数据临时丢失问题排查与解决

问题原因分析

你的问题本质是UI层与Form State的同步延迟加上React Table的不稳定依赖共同导致的:

  1. 输入值暂存与同步延迟:你的EditableTextCell组件用本地useState临时存储输入内容,只有在输入框失焦时才同步到React Hook Form的State中。当你操作另一个Field Array(比如添加Board Member)时,组件触发全局重新渲染,此时EditableTextCell的useEffect会监听来自Form State的旧值(还没同步本地输入的内容),把本地value重置为空,导致UI上数据“消失”。
  2. React Table依赖不稳定:在SystemUsersTable中,你每次渲染都会创建新的columns数组,这会让useReactTable频繁重新计算表格模型,不仅浪费性能,还会加剧数据显示的异常。

而当你添加新的System User时,对应的Field Array发生变化,useFieldArray返回的systemUsers数组更新,触发表格重新渲染——如果之前的输入已经失焦同步到了Form State,UI就会重新读取到正确的值,这就是你看到数据“重新出现”的原因。


解决方案

我们可以通过以下几步彻底解决这个问题:

1. 移除本地状态,实时同步Form State

取消EditableTextCell中的本地useState,让输入框直接和Form State绑定,输入内容实时同步到Form State,组件重新渲染时也会直接读取最新值:

// EditableTextCell.tsx 修改后
export const EditableTextCell = ({
  getValue,
  row: { index },
  column: { id },
  table,
  disabled = false,
}: CellContext<T, string> & { disabled?: boolean }) => {
  // 直接从Form State获取当前值
  const value = getValue();

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 实时同步输入值到Form State
    table.options.meta?.updateData(index, id, e.target.value);
  };

  return (
    <Input
      value={value}
      onChange={handleChange}
      disabled={disabled}
    />
  );
};

2. 缓存React Table的列配置,避免不必要重渲染

用useMemo缓存columns数组,确保只有在依赖变化时才更新,避免useReactTable频繁重建表格模型:

// SystemUsersTable.tsx 修改后
export const SystemUsersTable = ({
  data,
  isEditing,
  onRemove,
  onFieldChange,
}: SystemUsersTableProps) => {
  // 用useMemo缓存列配置,仅在isEditing变化时更新
  const columns = useMemo(() => [
    {
      accessorKey: "name",
      header: "Employee Name",
      cell: (props) => (
        <EditableTextCell {...props} disabled={!isEditing} />
      ),
    },
    // ... 其他列定义
  ], [isEditing]);

  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    meta: {
      updateData: (rowIndex, columnId, value) => {
        onFieldChange(rowIndex, columnId, value);
      },
      isEditing,
      onRemove,
    },
  });

  // ... 表格渲染逻辑
};

3. 可选:缓存Field Array数据,避免意外重渲染

虽然React Hook Form的useFieldArray返回的fields已经是memoized的,但可以给systemUsers加一层缓存,确保只有数据真的变化时才传递给表格:

// CompanyForm.tsx 修改后
const memoizedSystemUsers = useMemo(() => systemUsers, [systemUsers]);

<SystemUsersTable
  data={memoizedSystemUsers}
  isEditing={isEditing}
  onRemove={removeSystemUser}
  onFieldChange={(index, field, value) => {
    form.setValue(`systemUsers.${index}.${field}`, value);
  }}
/>

效果验证

修改完成后:

  • 你在System Users输入的内容会实时同步到Form State,不会因为操作Board Members而丢失
  • 两个Field Array的操作完全独立,修改其中一个不会影响另一个的数据显示
  • React Table的渲染性能也会得到提升,不会出现无意义的重新计算

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 14:05:29