• 18-19 College Green, Dublin 2
  • 01 685 9088
  • info@cunninghamwebsolutions.com
  • cunninghamwebsolutions
    Cunningham Web Solutions
    • HomeHome
    • About UsAbout Us
    • Our ServicesOur Services
      • Web Design
      • Digital Marketing
      • SEO Services
      • E-commerce Websites
      • Website Redevelopment
      • Social Media Services
    • Digital MarketingDigital Marketing
      • Adwords
      • Social Media Services
      • Email Marketing
      • Display Advertising
      • Remarketing
    • PortfolioPortfolio
    • FAQ’sFAQ’s
    • BlogBlog
    • Contact UsContact Us
    MENU CLOSE back  
    • Home
    • About Us
    • Our Services
      • back
      • Web Design
      • Digital Marketing
      • SEO Services
      • E-commerce Websites
      • Website Redevelopment
      • Social Media Services
    • Digital Marketing
      • back
      • Adwords
      • Social Media Services
      • Email Marketing
      • Display Advertising
      • Remarketing
    • Portfolio
    • FAQ’s
    • Blog
    • Contact Us

    React Form Validation With Formik And Yup

    You are here:
    1. Home
    2. Web Design
    3. React Form Validation With Formik And Yup
    Thumbnail for 25763

    As developers, it is our job to ensure that when users interact with the forms we set up, the data they send across is in the form we expect.

    In this article, we will learn how to handle form validation and track the state of forms without the aid of a form library.
    Next, we will see how the Formik library works. We’ll learn how it can be used incrementally with HTML input fields and custom validation rules. Then we will set up form validation using Yup and Formik’s custom components and understand how Yup works well with Formik in handling Form validation. We will implement these form validation methods to validate a simple sign up form I have set up.

    Note: This article requires a basic understanding of React.

    Form Validation In React

    On its own, React is powerful enough for us to be able to set up custom validation for our forms. Let’s see how to do that. We’ll start by creating our form component with initial state values. The following sandbox holds the code for our form:

    Form validation without the use of a library

    const Form = () => {
      const intialValues = { email: "", password: "" };
      const [formValues, setFormValues] = useState(intialValues);
      const [formErrors, setFormErrors] = useState({});
      const [isSubmitting, setIsSubmitting] = useState(false);
    }

    With the useState hook, we set state variables for the formValues, formErrors and isSubmitting.

    • The formValues variable holds the data the user puts into the input fields.
    • The formErrors variable holds the errors for each input field.
    • The isSubmitting variable is a boolean that tracks if the form is being submitted or not. This will be true only when there are no errors in the form.
    const submitForm = () => {
        console.log(formValues);
      };
    
     const handleChange = (e) => {
        const { name, value } = e.target;
        setFormValues({ ...formValues, [name]: value });
      };
    
    const handleSubmit = (e) => {
        e.preventDefault();
        setFormErrors(validate(formValues));
        setIsSubmitting(true);
      };
    
    const validate = (values) => {
        let errors = {};
        const regex = /^[^s@]+@[^s@]+.[^s@]{2,}$/i;
        if (!values.email) {
          errors.email = "Cannot be blank";
        } else if (!regex.test(values.email)) {
          errors.email = "Invalid email format";
        }
        if (!values.password) {
          errors.password = "Cannot be blank";
        } else if (values.password.length < 4) {
          errors.password = "Password must be more than 4 characters";
        }
        return errors;
      };
    
    useEffect(() => {
        if (Object.keys(formErrors).length === 0 && isSubmitting) {
          submitForm();
        }
      }, [formErrors]);

    Here, we have 4 form handlers and a useEffect set up to handle the functionality of our form.

    • handleChange
      This keeps the inputs in sync with the formValues state and updates the state as the user types.
    • validate
      We pass in the formValues object as a argument to this function, then based on the email and password meeting the validation tests, the errors object is populated and returned.
    • handleSubmit
      Whenever the form is submitted, the formErrors state variable is populated with whatever errors may exist using the setFormErrors(validate(formValues)) method.
    • useEffect
      Here, we check if the formErrors object is empty, and if isSubmitting is true. If this check holds true, then the submitForm() helper is called. It has single dependency, which is the formErrors object. This means it only runs when the formErrors object changes.
    • submitForm: this handles the submission of the form data.
    return (
        <div className="container">
          <h1>Sign in to continue</h1>
          {Object.keys(formErrors).length === 0 && isSubmitting && (
            <span className="success-msg">Signed in successfully</span>
          )}
          <form onSubmit={handleSubmit} noValidate>
            <div className="form-row">
              <label htmlFor="email">Email</label>
              <input
                type="email"
                name="email"
                id="email"
                value={formValues.email}
                onChange={handleChange}
                className={formErrors.email && "input-error"}
              />
              {formErrors.email && (
                <span className="error">{formErrors.email}</span>
              )}
            </div>
            <div className="form-row">
              <label htmlFor="password">Password</label>
              <input
                type="password"
                name="password"
                id="password"
                value={formValues.password}
                onChange={handleChange}
                className={formErrors.password && "input-error"}
              />
              {formErrors.password && (
                <span className="error">{formErrors.password}</span>
              )}
            </div>
            <button type="submit">Sign In</button>
          </form>
        </div>
      );

    Here, we pass in the handleChange helper functions to the inputs’ onChange attribute. We link the value of the inputs to the formValues object, making them controlled inputs. From the React docs, controlled inputs are inputs whose values are controlled by React. An input-error style is applied if there are any errors related to that specific input field. An error message is conditionally displayed beneath each input if there are any errors related to that specific input field. Finally, we check if there are any errors in the errors object and if isSubmitting is true. If these conditions hold true, then we display a message notifying the user that they signed in successfully.

    With this, we have a fully functional and validated form set up without the aid of a library. However, a form library like Formik with the aid of Yup can simplify the complexities of handling forms for us.

    What Are Formik And Yup?

    Right from the docs:

    “Formik is a small library that helps you with the 3 most annoying parts in handling forms:

    1. Getting values in and out of form state.
    2. Validation and error messages
    3. Handling form submission.

    Formik is a flexible library. It allows you to decide when and how much you want to use it. We can control how much functionality of the Formik library we use. It can be used with HTML input fields and custom validation rules, or Yup and the custom components it provides. Formik makes form validation easy! When paired with Yup, they abstract all the complexities that surround handling forms in React.

    Yup is a JavaScript object schema validator. While it has many powerful features, we’ll focus on how it helps us create custom validation rules so we don’t have to. This is a sample Yup object schema for a sign-up form. We’ll go into Yup and how it works in depth later in the article.

    const SignUpSchema = Yup.object().shape({
      firstName: Yup.string()
        .min(2, "Too Short!")
        .max(50, "Too Long!")
        .required("Firstname is required"),
    
      lastName: Yup.string()
        .min(2, "Too Short!")
        .max(50, "Too Long!")
        .required("Lastname is required"),
    
      phoneNumber: Yup.string()
        .required("Phone number is required")
        .matches(
    /^([0]{1}|+?[234]{3})([7-9]{1})([0|1]{1})([d]{1})([d]{7})$/g,
          "Invalid phone number"
        ),
    
      email: Yup.string().email().required("Email is required"),
    
      password: Yup.string()
        .required("Password is required")
        .min(6, "Password is too short - should be 6 chars minimum"),
    });

    Formik, HTML Input Fields And Custom Validation Rules

    The following sandbox holds the code for this form set up:

    The first thing we have to do is install Formik.

    npm i formik

    Then we can go ahead to import it in the file where we’ll make use of it.

    import { Formik } from "formik";

    Before creating the component, we need to create an initialValues and validate object which we’ll pass as props to the Formik component when we set it up. initialValues and validate are code snippets, not normal words.

    The decision to do this outside the component is not a technical one, but rather for readability of our code.

    const initialValues = {
      email: "",
      password: ""
    };

    initialValues: is an object that describes the initial values of the respective form fields. The name given to each key in the initialValues must correspond with the value of the name of the input field we want Formik to watch.

    const validate = (values) => {
      let errors = {};
      const regex = /^[^s@]+@[^s@]+.[^s@]{2,}$/i;
      if (!values.email) {
        errors.email = "Email is required";
      } else if (!regex.test(values.email)) {
        errors.email = "Invalid Email";
      }
      if (!values.password) {
        errors.password = "Password is required";
      } else if (values.password.length < 4) {
        errors.password = "Password too short";
      }
      return errors;
    };

    validate: this accepts a function that handles the form validation. The function accepts an object in the form of data values as an argument and validates each property in the object based on the rules defined. Each key in the values object must correspond with the name of the input field.

    const submitForm = (values) => {
      console.log(values);
    };

    onSubmit: This handles what happens after the user submits. The onSubmit prop takes a callback function that will only run when there are no errors, meaning the user inputs are valid.

    const SignInForm = () => {
      return (
        <Formik
          initialValues={initialValues}
          validate={validate}
          onSubmit={submitForm}
        >
          {(formik) => {
            const {
              values,
              handleChange,
              handleSubmit,
              errors,
              touched,
              handleBlur,
              isValid,
              dirty
            } = formik;
            return (
                <div className="container">
                  <h1>Sign in to continue</h1>
                  <form onSubmit={handleSubmit}>
                    <div className="form-row">
                      <label htmlFor="email">Email</label>
                      <input
                        type="email"
                        name="email"
                        id="email"
                        value={values.email}
                        onChange={handleChange}
                        onBlur={handleBlur}
                        className={errors.email && touched.email ? 
                        "input-error" : null}
                      />
                      {errors.email && touched.email && (
                        <span className="error">{errors.email}</span>
                      )}
                    </div>
    
                    <div className="form-row">
                      <label htmlFor="password">Password</label>
                      <input
                        type="password"
                        name="password"
                        id="password"
                        value={values.password}
                        onChange={handleChange}
                        onBlur={handleBlur}
                        className={errors.password && touched.password ? 
                         "input-error" : null}
                      />
                      {errors.password && touched.password && (
                        <span className="error">{errors.password}</span>
                      )}
                    </div>
    
                    <button
                      type="submit"
                      className={dirty && isValid ? "" : "disabled-btn"}
                      disabled={!(dirty && isValid)}>
                      Sign In
                    </button>
                  </form>
                </div>
            );
          }}
        </Formik>
      );
    };

    We pass in the initialValues object, and the submitForm and validate functions we defined earlier into Formik’s initialValues, onSubmit and validate props respectively.

    Using the render props pattern, we have access to even more props the Formik API provides.

    1. values
      This holds the values of the user inputs.
    2. handleChange
      This is the input change event handler. It is passed to the input field . It handles the changes of the user inputs.
    3. handleSubmit
      The form submission handler. It is passed into the form . This fires the function passed into the onSubmit prop whenever the form is submitted.
    4. errors
      This object holds the validation errors that correspond to each input field, and is populated with the definitions we passed into the Yup object schema.
    5. touched
      This is an object that watches if a form field has been touched. Each key corresponds to the name of the input elements and has a boolean value.
    6. handleBlur
      This is the onBlur event handler, and it is passed to the input field . When the user removes focus from an input, this function is called. Without it, if there are any errors in the input when it loses focus, the errors will only display when the user tries to submit.
    7. isValid
      Returns true if there are no errors (i.e. the errors object is empty) and false otherwise.
    8. dirty
      This prop checks if our form has been touched or not. We can use this to disable our submit button when the form loads initially.

    When the form is submitted, Formik checks if there are any errors in the errors object. If there are, it aborts the submission and displays the errors. To display the span using HTML inputs, we conditionally render and style the error message of each respective input field if the field has been touched and there are errors for that field.

    <button
      type="submit"
      className={!(dirty && isValid) ? "disabled-btn" : ""}
      disabled={!(dirty && isValid)}>
          Sign In
    </button>

    Also, we can add a visual cue to the button. The button is conditionally styled and disable it if there are errors in the errors object using the isValid and the dirty props.

    Validation Using Formik’s Components And Yup

    This sandbox holds the final code for this setup.

    npm i yup
    import { Formik, Form, Field, ErrorMessage } from "formik";
    import * as Yup from "yup";

    We install Yup, import the Field, Form, and the ErrorMessage components from Formik.

    Formik makes form validation easy! When paired with Yup, they abstract all the complexities that surround handling forms in React. With that we can then go ahead to create the schema we’ll be using for the sign in form using Yup. Instead of creating custom validations for each possible input field, which can be tedious, depending on the number of fields there are, we can leave that to Yup to handle.

    const SignInSchema = Yup.object().shape({
      email: Yup.string().email().required("Email is required"),
    
      password: Yup.string()
        .required("Password is required")
        .min(4, "Password is too short - should be 4 chars minimum"),
    });

    Yup works similarly to how we define propTypes in React. We created an object schema with Yup’s object function. We define the shape of the validation object schema and pass it into Yup’s shape() method. The required() method. This method takes a string as an argument, and this string will be the error message. that displays whenever a required field is left blank.

    This schema has two properties:

    • An email property that is a string type and is required.
    • A password property that is of number type but is not required.

    We can chain validation is Yup as seen above. The properties of the schema object match the name of the input fields. The docs go into the different validation methods available in Yup.

    const SignInForm = () => {
      return (
        <Formik
          initialValues={initialValues}
          validationSchema={signInSchema}
          onSubmit={(values) => {
            console.log(values);
          }}
        >
          {(formik) => {
            const { errors, touched, isValid, dirty } = formik;
            return (
              <div className="container">
                <h1>Sign in to continue</h1>
                <Form>
                  <div className="form-row">
                    <label htmlFor="email">Email</label>
                    <Field
                      type="email"
                      name="email"
                      id="email"
                      className={errors.email && touched.email ? 
                      "input-error" : null}
                    />
                    <ErrorMessage name="email" component="span" className="error" />
                  </div>
    
                  <div className="form-row">
                    <label htmlFor="password">Password</label>
                    <Field
                      type="password"
                      name="password"
                      id="password"
                      className={errors.password && touched.password ? 
                      "input-error" : null}
                    />
                    <ErrorMessage
                      name="password"
                      component="span"
                      className="error"
                    />
                  </div>
    
                  <button
                    type="submit"
                    className={!(dirty && isValid) ? "disabled-btn" : ""}
                    disabled={!(dirty && isValid)}
                  >
                    Sign In
                  </button>
                </Form>
              </div>
            );
          }}
        </Formik>
      );
    };

    While using HTML input fields get the job done, Formik’s custom components make things even easier for us, and reduce the amount of code we have to write! What are these custom components Formik provides us?

    1. Formik
      We’ve been using this for a while now. This is required for the other components to be usable.
    2. Form
      A wrapper that wraps the HTML element. It automatically links the onSubmit method to the form’s submit event.
    3. Field
      In the background, this automatically links the form input’s onChange, onBlur and value attributes to Formik’s handleChange, handleBlur, and values object respectively. It uses the name prop to match up with the state and automatically keeps the state in sync with the input value. With this component, we can decide to display it as an input field we want using it’s as property. For example, will render a textarea. By default, it renders an HTML input field.
    4. ErrorMessage
      It handles rendering the error message for its respective field based on the value given to the name prop, which corresponds to the ’s name prop. It displays the error message if the field has been visited and the error exists. By default, it renders a string is the component prop is not specified.

    We pass the signInSchema into Formik using the validationSchema prop. The Formik team loves the Yup validation library so they created a specific prop for Yup called validationSchema which transforms errors into objects and matches against their values and touched functions.

    Conclusion

    Users do not know or care how you handle form validation. However, for you the developer, it should be as painless a process as possible, and I believe Formik stands out as a solid choice in that regard.

    We have successfully looked at some of the options available to us when validating forms in React. We have seen how Formik can be used incrementally, and how it pairs well with Yup in handling form validation.

    Resources

    • Formik Docs
    • Yup Docs
    • Validation with Yup

    From our sponsors: React Form Validation With Formik And Yup

    Posted on 12th October 2020Web Design
    FacebookshareTwittertweetGoogle+share

    Related posts

    Archived
    22nd March 2023
    Archived
    18th March 2023
    Archived
    20th January 2023
    Thumbnail for 25788
    Handling Continuous Integration And Delivery With GitHub Actions
    19th October 2020
    Thumbnail for 25778
    A Monthly Update With New Guides And Community Resources
    19th October 2020
    Thumbnail for 25781
    Supercharge Testing React Applications With Wallaby.js
    19th October 2020
    Latest News
    • Archived
      22nd March 2023
    • Archived
      18th March 2023
    • Archived
      20th January 2023
    • 20201019 ML Brief
      19th October 2020
    • Thumbnail for 25788
      Handling Continuous Integration And Delivery With GitHub Actions
      19th October 2020
    • Thumbnail for 25786
      The Future of CX with Larry Ellison
      19th October 2020
    News Categories
    • Digital Marketing
    • Web Design

    Our services

    Website Design
    Digital Marketing
    SEO
    E-commerce
    Social Media Services
    Website Design
    Website Design

    A website is an important part of any business. Professional website development is an essential element of a successful online business.

    We provide website design services for every type of website imaginable. We supply brochure websites, E-commerce websites, bespoke website design, custom website development and a range of website applications. We love developing websites, come and talk to us about your project and we will tailor make a solution to match your requirements.

    You can contact us by phone, email or send us a request through our online form and we can give you a call back.

    More Information

    Digital Marketing
    Digital Marketing

    Our digital marketeers have years of experience in developing and excuting digital marketing strategies. We can help you promote your business online with the most effective methods to achieve the greatest return for your marketing budget. We offer a full service with includes the following:

    1. Social Media Marketing

    2. Email & Newsletter Advertising

    3. PPC - Pay Per Click

    4. A range of other methods are available

    More Information

    SEO
    SEO Services

    SEO is an essential part of owning an online property. The higher up the search engines that your website appears, the more visitors you will have and therefore the greater the potential for more business and increased profits.

    We offer a range of SEO services and packages. Our packages are very popular due to the expanse of on-page and off-page SEO services that they cover. Contact us to discuss your website and the SEO services that would best suit to increase your websites ranking.

    More Information

    E-commerce
    E-commerce Websites

    E-commerce is a rapidly growing area with sales online increasing year on year. A professional E-commerce store online is essential to increase sales and is a reflection of your business to potential customers. We provide professional E-commerce websites custom built to meet our clients requirements.

    Starting to sell online can be a daunting task and we are here to make that journey as smooth as possible. When you work with Cunningham Web Solutions on your E-commerce website, you will benefit from the experience of our team and every detail from the website design to stock management is carefully planned and designed with you in mind.

    More Information

    Social Media Services
    Social Media Services

    Social Media is becoming an increasingly effective method of marketing online. The opportunities that social media marketing can offer are endless and when managed correctly can bring great benefits to every business.

    Social Media Marketing is a low cost form of advertising that continues to bring a very good ROI for our clients. In conjuction with excellent website development and SEO, social media marketing should be an essential part of every digital marketing strategy.

    We offer Social Media Management packages and we also offer Social Media Training to individuals and to companies. Contact us to find out more.

    More Information

    Cunningham Web Solutions
    © Copyright 2025 | Cunningham Web Solutions
    • Home
    • Our Services
    • FAQ's
    • Account Services
    • Privacy Policy
    • Contact Us