Вопрос:
Я работаю над приложением Next.js 13 с TypeScript и пытаюсь создать общий компонент формы, используя форму реагирования. Цель состоит в том, чтобы иметь единый компонент формы, который может обрабатывать формы разных типов, такие как отчеты, клиенты и пользователи. Каждый тип формы имеет свой набор полей, но операции с формой (сохранение, сброс, обновление, удаление) остаются одинаковыми для всех типов.
Вот упрощенная версия того, чего я пытаюсь достичь:
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>
);
};Проблема:
У меня возникла проблема с проверкой типа TypeScript в компоненте GenericForm. Поскольку реактивная форма требует точного ввода полей формы, я не могу просто использовать тип объединения для данных моей формы. Однако мне нужен компонент GenericForm, чтобы принимать различные типы исходных данных в зависимости от отображаемой формы.
Я не уверен, как правильно обрабатывать проверку типов и условную отрисовку в компоненте GenericForm, чтобы разместить различные типы данных формы, сохраняя при этом безопасность типов.
Ожидаемый результат:
Я ожидаю, что у меня будет один компонент GenericForm, который сможет обрабатывать формы разных типов, отображая соответствующие поля в зависимости от типа предоставленных исходных данных. Кроме того, мне нужно убедиться, что проверка типов TypeScript правильно обрабатывается внутри компонента.






Вы на правильном пути. Я бы продолжил то, что вы сделали, и заставил бы GenericForm привести общий аргумент.
Определите компонент следующим образом.
const GenericForm = <T,>({ initialData, onSubmit }:FormProps<T>) => {
Тогда используйте его вот так <GenericForm<ReportFormData> initialData = {{reportField:""}} onSubmit = {()=>{}}/>
Это должно сделать GenericForm безопасным для типов initialData и onSubmit.
Вот пример с игровой площадки TS 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.info(data)}/>
}
Я добавил код и ссылку на игровую площадку TS, показывающую один из способов порадовать useForm принятием дженерика.
Спасибо, но как насчет useForm ``` const form = useForm<T>({solver: zodResolver(InitialReportValidationSchema), defaultValues: report, }); ``` он не принимает ничего общего