I am currently using this amazing hook I found a couple months ago on the internet somewhere and can't find the article I found it anymore, but basically the issue I have is that when I have a large form and I tab to the next field if I use the onBlur it runs the validation for every field so all fields that are required automatically become red and show an error (because they have nothing in them and my error css).
I want to wait until the field has at least been entered into and then left before the validation related to that specific field.
Basically I want to know if there is a way I can somehow wait until the input has been selected at least once. The only thing I can think of would be having a separate hook for each input in the form or somehow attaching an event to each field- true/false for if it has been selected at least once, but don't know how that would get implemented.
import { useState, useEffect } from "react";
const useFormValidation = (initialState, validate, authenticate) => {
const [values, setValues] = useState(initialState);
const [errors, setErrors] = useState({});
const [isSubmitting, setSubmitting] = useState(false);
useEffect(() => {
if (isSubmitting) {
const noErrors = Object.keys(errors).length === 0;
if (noErrors) {
authenticate();
setSubmitting(false);
} else {
setSubmitting(false);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [errors]);
const handleChange = (event) => {
setValues({
...values,
[event.target.name]: event.target.value
});
}
const handleChangeChecked = (event) => {
setValues({...values, [event.target.name] : event.target.checked });
}
//THIS IS THE FUNCTION I AM TALKING ABOUT
const handleBlur = () => {
const validationErrors = validate(values);
setErrors(validationErrors);
}
const handleSubmit = (event) => {
event.preventDefault();
const validationErrors = validate(values);
setErrors(validationErrors);
setSubmitting(true);
}
return {
handleSubmit,
handleChange,
handleChangeChecked,
handleBlur,
values,
errors,
isSubmitting
};
}
export default useFormValidation;
Here is a sample validation also which is the second field passed into useFormValidation function.
const validateCareTeam = (values) => {
let errors = {};
// First Name Errors
if (!values.firstName) {
errors.firstName = "First name is required";
}
// Last Name Errors
if (!values.lastName) {
errors.lastName = "Last name is required";
}
// Email Error
if (values.email && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) {
errors.email = "Please enter a valid email address";
}
const phoneno = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/
// Phone Number Errors
if (!values.phone) {
errors.phoneNumber = "Phone number is required";
} else if (!values.phone.match(phoneno)) {
errors.phoneNumber = "Please enter a phone number with 10 digits. 1 not necessary"
}
return errors;
}
export default validateCareTeam;
So basically if the use tabs after first name then all other required fields- last name and phone number turn red.
I would prefer to not event run the validation until the submit button is hit, but I have been asked for validation immediately.