Easy Error Handling and Data Validation with Yup
Introduction
Formik has first class support for yup. It's a declarative way to handle both synchronous and asynchronous error handling. It has methods that allow you to transform, and do custom error checking when necessary.
Declarative Errors
To use yup you can import it piece by piece. Our Formik values are in the shape of an object. So we import the object validation from yup. Also we will be validating just strings so we'll import the string validator as well.
To put it together we first declare we want to check a shape.
object().shape({});
Then it expects that we describe the shape of our data using the keys that map to the keys on our values. In our case we want to check our firstName isn't empty.
Inside of our shape we give it our object, and specify that firstName is a string() and that it is required(). The value you pass to the required() call will be the message when this validation fails. In our case the message is Required.
{
firstName: string().required("Required"),
}
import { object, string } from "yup";
const NameValidation = object().shape({
firstName: string().required("Required"),
});
Using with Formik
Formik has first class support, so rather than calling validate function we provide a validationSchema. Formik internals know that it's a yup schema. It doesn't matter if you have sync or async validations in Yup it'll still work.
Formik knows how to map the errors returned from yup to the appropriate structure for its own internal error system.
<Formik
initialValues={{
firstName: "",
}}
onSubmit={handleSubmit}
validationSchema={NameValidation}
/>
Putting it All Together
import React from "react";
import { Formik, Form, Field, useField, ErrorMessage } from "formik";
import { object, string } from "yup";
const NameValidation = object().shape({
firstName: string().required("Required"),
});
const MySpecialField = () => {
const [field, meta] = useField("firstName");
return (
<div>
<input {...field} className="border-2" />
{meta.touched && meta.error && <div>{meta.error}</div>}
</div>
);
};
function App() {
const handleSubmit = (values) => {
console.log(values);
};
return (
<div className="App">
<Formik
initialValues={{
firstName: "",
}}
onSubmit={handleSubmit}
validationSchema={NameValidation}
>
{() => {
return (
<Form className="h-screen flex content-center flex-col justify-center">
<div className="space-x-4 flex content-center justify-center">
<div>
<Field name="firstName" className="border-2" />
<ErrorMessage name="firstName" component="div" />
</div>
<MySpecialField />
<button
type="submit"
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
>
Submit
</button>
</div>
</Form>
);
}}
</Formik>
</div>
);
}
export default App;