reactjs TypeScript中可重复使用的react-hook形式useFieldArray组件

ioekq8ef  于 2022-12-03  发布在  React
关注(0)|答案(1)|浏览(169)

我正在使用react-hook-form的useFieldArray挂钩创建一个可重用的动态表单组件,但在正确添加field的类型时遇到了问题。
为了设置表单,我添加了一个类型和一些defaultValues:

export type NamesArray = { name: string; required: boolean }[];

export type FormValues = { randomFormValue: string; namesArray: NamesArray };

const defaultValues = {
  namesArray: [{ name: "Me", required: true }]
};

现在,当我使用我的可重用表单组件<NamesForm />时,它应该总是知道使用该组件的表单的namesArray部分,这样我就可以:

type Props<T> = {
  control: Control<T>;
  register: UseFormRegister<T>;
};

export function NamesForm<T extends NamesArray>({
  control,
  register
}: Props<T>) {
  const { fields, append } = useFieldArray<T, "namesArray", "id">({
    control,
    name: "namesArray"
  });

  return (
    <>
      {fields.map((field, index) => {
        return field.required && <input {...register(`namesArray.${index}.name` as const)} />;
      })}

      <button type="button" onClick={() => append({})}>
        Append
      </button>
    </>
  );
}

在这里,为了使组件可重用,我使用了通用的道具。
我的问题是,即使我已经明确地说我的通用T应该包含一个namesArray,TS似乎不能接受,并给我错误:
型别'string'不满足条件约束'ArrayPath'。
而且对我来说,不定义field的类型是不够的,因为我想使用field的属性,比如required
代码沙箱:https://codesandbox.io/s/controlled-field-array-forked-vooe9w?file=/src/NamesForm.tsx:139-214

ycl3bljg

ycl3bljg1#

您的一般字段值T应该扩充包含namesArray的对象,而不是数组。

type Name = {
  name: string;
  required: boolean;
};
type FormValuesWithNamesArray = {
  namesArray: Name[];
};
export function NamesForm<T extends FormValuesWithNamesArray>

但即使进行了这样的更改,错误仍然存在。对我来说起作用的是删除泛型:

export type = Name {
  name: string;
  required: boolean;
}
export type FormValuesWithNamesArray = {
  namesArray: Name[];
  [key: string]: any;
}
type Props = {
  control: Control<FormValuesWithNamesArray>;
  register: UseFormRegister<FormValuesWithNamesArray>;
};

export function NamesForm({ control, register }: Props) {
  const { fields, append } = useFieldArray({
    control,
    name: "namesArray",
  });

  return (
    <>
      {fields.map((field, index) => {
        return (
          field.required && (
            <input {...register(`namesArray.${index}.name` as const)} />
          )
        );
      })}

      <button
        type="button"
        onClick={() => append({ name: "", required: false })}
      >
        Append
      </button>
    </>
  );
}

相关问题