useForm Hook
A lightweight custom React Hook for form state management with validation and TypeScript support
Code
import { useState, ChangeEvent } from 'react';
type ValidationRules<T> = {
[K in keyof T]?: (value: T[K]) => string | null;
};
type FormErrors<T> = { [K in keyof T]?: string };
function useForm<T>(
initialValues: T,
validationRules?: ValidationRules<T>
) {
const [values, setValues] = useState<T>(initialValues);
const [errors, setErrors] = useState<FormErrors<T>>({});
const handleChange = (e: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setValues(prev => ({ ...prev, [name]: value }));
};
const validate = (): boolean => {
__TOKEN_21__ (!validationRules) return true;
const newErrors: FormErrors<T> = {};
Object.entries(validationRules).forEach(([key, rule]) => {
__TOKEN_24__ (rule) {
const error = rule(values[key as keyof T]);
__TOKEN_26__ (error) newErrors[key as keyof T] = error;
}
});
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const reset = () => setValues(initialValues);
return { values, errors, handleChange, validate, reset };
}
// Usage example
// const { values, errors, handleChange, validate, reset } = useForm({
// email: '',
// password: ''
// }, {
// email: (val) => !val ? 'Email is required' : !/^\S+@\S+\.\S+$/.test(val) ? 'Invalid email' : null,
// password: (val) => !val ? 'Password is required' : val.length < 6 ? 'Min 6 chars' : null
// });