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相关问答推荐

为什么AB和CD这两种类型在TypScript中可以相互分配?

端点之间的TEK查询缓存

JS Redux Devtools扩展不工作

类型脚本强制泛型类型安全

打印脚本丢失函数的泛型上下文

无法正确推断嵌套泛型?

对扩展某种类型的属性子集进行操作的函数

React重定向参数

在HighChats列时间序列图中,十字准线未按预期工作

如何使所有可选字段在打印脚本中都是必填字段,但不能多或少?

在类型脚本中创建泛型类型以动态追加属性后缀

Fp-ts使用任务的最佳方法包装选项

如何在方法中正确地传递来自TypeScrip对象的字段子集?

判断映射类型内的键值的条件类型

是否可以通过映射类型将函数参数约束为预定义类型?

如何使用TypeScrip在EXPO路由链路组件中使用动态路由?

如何从上传文件中删除预览文件图标?

无法缩小深度嵌套对象props 的范围

我可以将一个类型数组映射到TypeScrip中的另一个类型数组吗?

更漂亮的格式数组<;T>;到T[]