Skip to content

Instantly share code, notes, and snippets.

@mildronize
Last active June 27, 2023 01:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mildronize/2cbc0e7dcf2a3e7b54e783e1f8e0727d to your computer and use it in GitHub Desktop.
Save mildronize/2cbc0e7dcf2a3e7b54e783e1f8e0727d to your computer and use it in GitHub Desktop.
My Own React Hook Form
// Inspired by react-hook-form
import { useRef } from 'react';
import { z } from 'zod';
interface UseFormOption<T> {
defaultValues: T;
schema: z.AnyZodObject;
}
function createRef<T extends object>(object: T) {
return Object.fromEntries(
Object.entries(object).map(([key, value]) => [key, useRef<HTMLInputElement>(null)])
) as Record<keyof T, React.RefObject<HTMLInputElement>>;
}
function createRefValue<T extends Record<keyof T, React.RefObject<HTMLInputElement>>>(object: T) {
const result = {} as Record<string, string>;
for (const [key, value] of Object.entries<React.RefObject<HTMLInputElement>>(object)) {
result[key] = value.current?.value ?? '';
}
return result as Record<keyof T, string>;
}
export function useForm<TFormObject extends object>(option: UseFormOption<TFormObject>) {
const ref = createRef(option.defaultValues);
const register = (formKey: keyof TFormObject) => ({
ref: ref[formKey],
});
// Still Error, don't finish yet
const handleSubmit = (data?: (data: TFormObject)) => {
const result = option.schema.safeParse(createRefValue(ref));
if (!result.success) {
return result.error.flatten().fieldErrors;
}
return {};
};
const errors = {};
return { register, handleSubmit, errors };
}
// Path: src/pages/SignIn.tsx
const productInputSchema = z.object({
name: z.string().nonempty(),
price: z.number().min(0),
stock: z.number().min(0),
});
type FormInput = z.infer<typeof productInputSchema>;
function Named() {
const { register, handleSubmit, errors } = useForm<FormInput>({
schema: productInputSchema,
defaultValues: {
name: '',
price: 0,
stock: 0,
},
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment