Question:

我正在使用TypScript开发Next.js 13应用程序,并且我正在try 使用react-hook-form创建一个通用表单组件.目标是拥有一个可以处理不同类型表单(例如报表、客户端和用户)的单一表单组件.每种类型的表单都有自己的一组字段,但表单操作(保存、重置、更新、删除)在所有类型中保持相同.

这是我试图实现的目标的简化版本:

import { FC } from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';

// Define different types of form data
type ReportFormData = {
  reportField: string;
};

type ClientFormData = {
  clientField: string;
};

type UserFormData = {
  userField: string;
};

// Define props for the generic form component
type FormProps<T> = {
  initialData: T;
  onSubmit: SubmitHandler<T>;
};

// Create the generic form component
const GenericForm: FC<FormProps> = ({ initialData, onSubmit }) => {
  const { register, handleSubmit, reset } = useForm({
    defaultValues: initialData,
  });

  const onSubmitHandler: SubmitHandler<T> = (data) => {
    onSubmit(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmitHandler)}>
      {/* How can I conditionally render fields based on the type of data? */}
      {/* How to properly handle type checking in this scenario? */}
      
      {/* Placeholder for save operation */}
      <button type="submit">Save</button>
      
      {/* Placeholder for reset operation */}
      <button type="button" onClick={() => reset(initialData)}>
        Reset
      </button>
      
      {/* Placeholder for update operation */}
      {/* Placeholder for delete operation */}
    </form>
  );
};

问题 :

我面临着GenericForm组件内的TypScript类型判断问题.由于react-hook-form需要对表单字段进行精确的输入,因此我不能简单地对表单数据使用联合类型.然而,我需要GenericForm组件根据所呈现的表单接受不同类型的初始数据.

我不确定如何正确处理GenericForm组件内的类型判断和条件呈现,以适应不同类型的表单数据,同时保持类型安全.

预期yields :

我希望拥有一个单一的GenericForm组件,它可以处理不同类型的表格,并根据提供的初始数据类型呈现适当的字段.此外,我需要确保在组件内正确处理TypScript类型判断.

推荐答案

你走在正确的道路上.我会扩展你所做的事情,并让GenericForm个人采取一般性的论点.

这样定义组件.

const GenericForm = <T,>({ initialData, onSubmit }:FormProps<T>) => {

那就像这样用<GenericForm<ReportFormData> initialData={{reportField:""}} onSubmit={()=>{}}/>

这应该使GenericForm具有类型安全initialDataonSubmit

以下是TS playground https://tsplay.dev/WG05vw的示例

import React from 'react';
import { useForm, SubmitHandler, FieldValues, DefaultValues } from 'react-hook-form';

// Define different types of form data
type ReportFormData = {
  reportField: string | null;
};

type ClientFormData = {
  clientField: string | null;
};

type UserFormData = {
  userField: string | null;
};

// Define props for the generic form component 
type FormProps<T extends FieldValues> = {
  initialData: DefaultValues<T>;
  onSubmit: SubmitHandler<T>;
};

// Create the generic form component
const GenericForm =<T extends FieldValues,> ({ initialData, onSubmit }:FormProps<T>) => {
  const { register, handleSubmit, reset } = useForm<T>({
    defaultValues: initialData,
  });

  const onSubmitHandler: SubmitHandler<T> = (data) => {
    onSubmit(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmitHandler)}>
      {/* How can I conditionally render fields based on the type of data? */}
      {/* How to properly handle type checking in this scenario? */}
      
      {/* Placeholder for save operation */}
      <button type="submit">Save</button>
      
      {/* Placeholder for reset operation */}
      <button type="button" onClick={() => reset(initialData)}>
        Reset
      </button>
      
      {/* Placeholder for update operation */}
      {/* Placeholder for delete operation */}
    </form>
  );
};


const ReportFormComponent = () =>{

  return <GenericForm<ReportFormData> initialData={{reportField:null}} onSubmit={(data)=>console.log(data)}/>
}

Typescript相关问答推荐

Typescript:假设foo不在类型栏中,而它在:如何调试

VS代码1.88.0中未出现自动导入建议

在Angular中,如何在文件上传后清除文件上传文本框

如果一个变量不是never类型,我如何创建编译器错误?

使用axios在ngOnInit中初始化列表

我想创建一个只需要一个未定义属性的打字脚本类型

如何重构长联合类型?

记录键的泛型类型

在另一个类型的函数中,编译器不会推断模板文字类型

在Cypress中,是否可以在不标识错误的情况下对元素调用.Click()方法?

如何从对象或类动态生成类型

如何连接属性名称和值?

有没有办法传递泛型类型数组,以便推断每个元素的泛型类型?

map 未显示控制台未显示任何错误@reaction-google-map/api

必需的输入()参数仍然发出&没有初始值设定项&q;错误

在REACT查询中获取未定义的isLoading态

React中的效果挂钩在依赖项更新后不会重新执行

无法使用prisma中的事务更新记录

两个子组件共享控制权

递归地排除/省略两种类型之间的公共属性