92 lines
2.1 KiB
TypeScript
92 lines
2.1 KiB
TypeScript
import { useRef, type InputHTMLAttributes } from "react";
|
|
|
|
type defaultValues = Record<string, any>;
|
|
|
|
interface Props<T extends defaultValues = defaultValues> {
|
|
initialValues?: Partial<T>;
|
|
}
|
|
|
|
type InputElements =
|
|
| HTMLInputElement
|
|
| HTMLSelectElement
|
|
| HTMLTextAreaElement
|
|
;
|
|
|
|
interface UseFormReturns<T extends defaultValues> {
|
|
getValue: () => T;
|
|
setValue: (name: keyof T, value: string | number) => void;
|
|
setValues: (values: Partial<T>) => void;
|
|
bindInput: (name: keyof T) => InputHTMLAttributes<InputElements>;
|
|
// onSubmit: (values: T) => (ev: React.FormEvent) => void
|
|
onSubmit: (fn: (values: T) => void) => (ev: React.FormEvent) => void
|
|
}
|
|
|
|
function useForm<T extends defaultValues>({ initialValues }: Props<T>) {
|
|
const inputs = useRef<Partial<Record<keyof T, InputElements>>>({});
|
|
const values = useRef<T>({ ...initialValues } as T);
|
|
const inst = useRef<UseFormReturns<T>>();
|
|
|
|
if (!inst.current) {
|
|
const getValue = () => {
|
|
return values.current;
|
|
}
|
|
|
|
const setValue = (name, value) => {
|
|
console.log(inputs.current[name], name);
|
|
|
|
if (inputs.current[name]) {
|
|
values.current[name as keyof T] = value;
|
|
inputs.current[name].value = value;
|
|
}
|
|
}
|
|
|
|
const setValues = (values) => {
|
|
Object.keys(values).forEach((key) => {
|
|
setValue(key, values[key]);
|
|
});
|
|
}
|
|
|
|
const bindInput = (name: string) => {
|
|
console.log('bindinput')
|
|
|
|
return {
|
|
name,
|
|
id: name,
|
|
ref: (target) => {
|
|
console.log('ref', target);
|
|
|
|
if (target) {
|
|
inputs.current[name as keyof T] = target;
|
|
}
|
|
},
|
|
defaultValue: initialValues[name],
|
|
onChange: (ev) => {
|
|
const { name, value } = ev.target;
|
|
|
|
values.current[name as keyof T] = value;
|
|
},
|
|
}
|
|
}
|
|
|
|
const onSubmit = (fn: (values: T) => void) => {
|
|
return (ev: React.FormEvent) => {
|
|
ev.preventDefault();
|
|
|
|
fn(getValue());
|
|
}
|
|
}
|
|
|
|
inst.current = {
|
|
getValue,
|
|
setValue,
|
|
setValues,
|
|
bindInput,
|
|
onSubmit,
|
|
};
|
|
}
|
|
|
|
return inst.current;
|
|
}
|
|
|
|
export default useForm;
|