In this blog, we will create a state validation hook in react using Yup. I am also going to use ramda a functional library (if you are not using it already, do give it a try).
Yup
Yup is a JavaScript schema builder for value parsing and validation. Define a schema, transform a value to match, validate the shape of an existing value, or both. Yup schema are extremely expressive and allow modeling complex, interdependent validations, or value transformations.
Yup schema
Let’s take a simple example of a login form, check this playground for more complex use cases.
const schema = yup.object().shape({
email: yup
.string()
.trim()
.required("Email is required")
.email("Email is invalid"),
password: yup.string().trim().required("Password is required")
});
This is the first cut of our validation hook.
It takes in the schema
and the values
as arguments.
We can now use it like shown below.
const {
errors,
handleFormSubmit
} = useValidation(schema, formValues);
Our validation hook gives us errors
object and a function named handleFormSubmit
.
We can call handleFormSubmit
on the form’s submit event or
it can also be done manually if we have to.
The handleFormSubmit
will take two arguments,
an event and a callback which will be called
upon successful validation.
This is how we can make use of it.
return (
<form onSubmit={(e) => handleFormSubmit(e, handleSubmit)}>
Check this form live in action.
As you try filling the form, you may notice that the validations are not dynamic, we have to submit the form in order to re-validate it.
Let’s make it dynamic by adding a new function to the hook.
const reValidate = () => {
if (!isValidating) return;
try {
schema.validateSync(formValues, { abortEarly: false });
setErrors({});
return true;
} catch (err) {
if (err.name === "ValidationError") {
const errs = mergeAll(
err.inner.flatMap((e) => ({ [e.path]: e.errors }))
);
setErrors(errs);
return false;
}
}
};
We can now call this function in our component when the state changes and the validations will be running dynamically after the first form submit (Assuming we dont want to show the errors to the user as soon as they start typing).
useEffect(() => {
reValidate();
}, [formValues]);
Here is our awesome dynamic form
Let’s use this same hook for more complex validations, check the following example.
Here is the full code for our useValidation hook.
Finally,
In this post, we explored how we could use react hooks and use those for our own custom validator.