Last active
March 19, 2022 14:12
-
-
Save alphaolomi/1e2c6e6b6bbbda85c88f8bf5f749b8ac to your computer and use it in GitHub Desktop.
RHF Smart Form
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import { useForm, UseFormReturn, SubmitHandler } from "react-hook-form"; | |
type InputProps = React.DetailedHTMLProps< | |
React.InputHTMLAttributes<HTMLInputElement>, | |
HTMLInputElement | |
>; | |
const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => ( | |
<label htmlFor={props.name}> | |
{props.name}: | |
<input ref={ref} {...props} /> | |
</label> | |
)); | |
Input.displayName = "Input"; | |
type Option = { | |
label: React.ReactNode; | |
value: string | number | string[]; | |
}; | |
type SelectProps = React.DetailedHTMLProps< | |
React.SelectHTMLAttributes<HTMLSelectElement>, | |
HTMLSelectElement | |
> & { options: Option[] }; | |
const Select = React.forwardRef<HTMLSelectElement, SelectProps>( | |
({ options, ...props }, ref) => ( | |
<select ref={ref} {...props}> | |
{options.map(({ label, value }, index) => ( | |
<option key={index} value={value}> | |
{label} | |
</option> | |
))} | |
</select> | |
) | |
); | |
Select.displayName = "Select"; | |
type FormProps<TFormValues> = { | |
onSubmit: SubmitHandler<TFormValues>; | |
children: (methods: UseFormReturn<TFormValues>) => React.ReactNode; | |
}; | |
const Form = <TFormValues extends Record<string, any> = Record<string, any>>({ | |
onSubmit, | |
children, | |
}: FormProps<TFormValues>) => { | |
const methods = useForm<TFormValues>(); | |
return ( | |
<form onSubmit={methods.handleSubmit(onSubmit)}>{children(methods)}</form> | |
); | |
}; | |
type FormValues = { | |
firstName: string; | |
lastName: string; | |
sex: string; | |
}; | |
export default function App() { | |
const onSubmit = (data: FormValues) => console.log(data); | |
const genders = [ | |
{ label: "Female", value: "female" }, | |
{ label: "Male", value: "male" }, | |
{ label: "Other", value: "other" }, | |
]; | |
return ( | |
<Form<FormValues> onSubmit={onSubmit}> | |
{({ register }) => ( | |
<> | |
<Input {...register("firstName")} /> | |
<Input {...register("lastName")} /> | |
<Select {...register("sex")} options={genders} /> | |
<Input type="submit" /> | |
</> | |
)} | |
</Form> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment