I have a login and register form(from react hooks) in my application. I want to reuse common fields for both forms.
Therefore, I have created components like emailField, passwordField etc. Since register form contains fields in login form I have derived RegisterFormFields from LoginFormFields. and in emailField.tsx I have defined
interface EmailFieldParameterTypes {
register: UseFormRegister<LoginFormFields>;
errors: FieldErrors<LoginFormFields>;
}
where I hope to be able call emailField both with UseFormRegister<RegisterFormFields>
and UseFormRegister<LoginFormFields>
but I was not. the typescript compiler gave
Type 'UseFormRegister<RegisterFormFields>' is not assignable to type 'UseFormRegister<LoginFormFields>'.
Type 'LoginFormFields' is missing the following properties from type 'RegisterFormFields': username, firstname, surnamets(2322)
emailField.tsx(5, 5): The expected type comes from property 'register' which is declared here on type 'IntrinsicAttributes & EmailFieldParameterTypes'
error even though RegisterFormFields extends LoginFormFields. I have also tried somethings with generics but it didn't workout. appriciated for any help.
referred files:
emailField.tsx
import { FieldErrors, UseFormRegister } from 'react-hook-form';
import { LoginFormFields } from '../../login/loginForm';
interface EmailFieldParameterTypes {
register: UseFormRegister<LoginFormFields>;
errors: FieldErrors<LoginFormFields>;
}
const EmailField = ({ register, errors }: EmailFieldParameterTypes) => {
return (
<label className="flex flex-col gap-1">
<div>Email</div>
<input
className="p-2 border border-gray-500 shadow bg-gray-200"
id="email-input"
type="email"
placeholder={"enter your email"}
{...register("email", { required: "email is required!" })}
/>
{errors.email && <p className="text-red-400">{errors.email.message}</p>}
</label>
);
};
export default EmailField;
registerForm.tsx
import { useForm } from "react-hook-form";
import EmailField from "../components/form-fields/emailField";
import PasswordField from "../components/form-fields/passwordField";
import UsernameField from "../components/form-fields/usernameField";
import { LoginFormFields } from "../login/loginForm";
export interface RegisterFormFields extends LoginFormFields {
username: string
firstname: string
surname: string
}
const RegisterForm = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<RegisterFormFields>()
const onSubmit = handleSubmit((data) => console.log(data))
return (
<form onSubmit={onSubmit}
className="flex w-100 px-12 py-8 flex-col gap-3 max-w-xl shadow 2xl border border-gray-300 rounded-2xl">
<EmailField register={register} errors={errors} />
<PasswordField register={register} errors={errors} />
<UsernameField register={register} errors={errors} />
<button className="bg-blue-400 rounded shadow text-white text-lg p-2">
Giriş Yap
</button>
</form>
)
};
export default RegisterForm;
LoginForm.tsx
import { useForm } from "react-hook-form";
import EmailField from "../components/form-fields/emailField";
import PasswordField from "../components/form-fields/passwordField";
export interface LoginFormFields {
email: string
password: string
}
const LoginForm = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<LoginFormFields>()
const onSubmit = handleSubmit((data) => console.log(data))
return (
<form onSubmit={onSubmit}
className="flex w-100 px-12 py-8 flex-col gap-3 max-w-xl shadow 2xl border border-gray-300 rounded-2xl">
<EmailField register={register} errors={errors} />
<PasswordField register={register} errors={errors} />
<button className="bg-blue-400 rounded shadow text-white text-lg p-2">
Giriş Yap
</button>
</form>
)
};
export default LoginForm;
I'd ensure the types for your shared fields are generic, and extend LoginFormFields
.
For example, replacing emailField.tsx
interface EmailFieldParameterTypes<T extends LoginFormFields> {
register: UseFormRegister<T>;
errors: FieldErrors<T>;
}
const EmailField = <T extends LoginFormFields>({ register, errors }:
EmailFieldParameterTypes<T>) => {
...
};