Skip to content

Instantly share code, notes, and snippets.

@alphaolomi
Last active March 19, 2022 14:12
Show Gist options
  • Save alphaolomi/1e2c6e6b6bbbda85c88f8bf5f749b8ac to your computer and use it in GitHub Desktop.
Save alphaolomi/1e2c6e6b6bbbda85c88f8bf5f749b8ac to your computer and use it in GitHub Desktop.
RHF Smart Form
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