The useForm hook manages the internal state of a form and automatically tracks validation. It requires an initial state object where each key represents a field. Each field must be an object containing a value and a validator function. The validator function must return an object with isValid (boolean) and errorMessages (array of strings).
The hook returns a tuple: [formData, setFormData].
formData: An object mirroring the initial state, but with isValid and errorMessages properties added to every field based on the validator's output.setFormData: A change handler function that takes a field name and a new value, updates the state, and re-runs the validator for that field.
import { useForm } from 'react-use-custom-hooks';
const initialState = {
name: {
value: '',
validator: (value) => {
return value.length > 0
? { isValid: true, errorMessages: [] }
: { isValid: false, errorMessages: ['Name is required'] };
},
},
age: {
value: '',
validator: (value) => {
if (!value) return { isValid: false, errorMessages: ['Age is required'] };
if (value > 120) return { isValid: false, errorMessages: ['Age should be less than 120'] };
return { isValid: true, errorMessages: [] };
},
},
};
function MyForm() {
const [formData, setFormData] = useForm(initialState);
const { name, age } = formData;
// Check if the entire form is valid
const isFormValid = Object.values(formData).every(field => field.isValid);
return (
<form>
<input
value={name.value}
onChange={e => setFormData('name', e.target.value)}
/>
{name.errorMessages.length > 0 && <span>{name.errorMessages[0]}</span>}
<input
type="number"
value={age.value}
onChange={e => setFormData('age', e.target.value)}
/>
{age.errorMessages.length > 0 && <span>{age.errorMessages[0]}</span>}
<p>Form is {isFormValid ? 'valid' : 'invalid'}</p>
</form>
);
}