SajZ
SajZ

Reputation: 260

Formik ReactBoostrap Form not validating

I have formik form build on the react-boostrap form. I have a custom onchange for handling the inputs. The issue is that validation error throw even if there is a value in the form field. Also, If some value is typed then error message is not gone. I guess the validation is not working at all. Please help me on this.

This is the code for react-bootstrap form https://react-bootstrap.github.io/components/forms/#forms-validation-libraries

import React from "react";
import * as yup from "yup";

export default function StepByStepForm() {
  const [myForm, setMyForm] = useState({});

  const handleInput = (e) => {
    const value = e.target.value;
    const name = e.target.name;
    setMyForm((prev) => ({
      ...prev,
      [name]: value,
    }));
  };

  const form1schema = yup.object({
    company_name: yup.string().required(),
  });

  function Step1Form() {
    return (
      <Formik validationSchema={form1schema}>
        {({
          touched,
          isValid,
          isInvalid,
          errors,
          handleBlur,
          handleChange,
          values,
          validateForm,
        }) => (
          <Form noValidate className="formstep1">
            <Form.Group controlId="addCompany">
              <Form.Label>Company Name*</Form.Label>
              <Form.Control
                name="company_name"
                type="text"
                value={myForm.company_name}
                onChange={handleInput} // have my custom handling
                isInvalid={!!errors.company_name}
              />
              <Form.Control.Feedback type="invalid">
                {errors.company_name}
              </Form.Control.Feedback>
            </Form.Group>

            <div className="step-progress-btn">
              <Button variant="primary" onClick={() => validateForm()}>
                Validate
              </Button>
            </div>
          </Form>
        )}
      </Formik>
    );
  }

  return <div>Step1Form()</div>;
}

Upvotes: 1

Views: 1640

Answers (2)

SajZ
SajZ

Reputation: 260

The issue was that Formik-Yup needed the onChange={handleChange} to validate

If you have custom or additional functionality on top of handleChange then you need to add the eventlistener on top of handlechange

import React from "react";
import * as yup from "yup";

export default function StepByStepForm() {
  const [myForm, setMyForm] = useState({});

  const handleInput = (e) => {
    const value = e.target.value;
    const name = e.target.name;
    setMyForm((prev) => ({
      ...prev,
      [name]: value,
    }));
  };

  const form1schema = yup.object({
    company_name: yup.string().required(),
  });

  function Step1Form() {
    return (
      <Formik validationSchema={form1schema}>
        {({
          touched,
          isValid,
          isInvalid,
          errors,
          handleBlur,
          handleChange,
          values,
          validateForm,
        }) => (
          <Form noValidate className="formstep1">
            <Form.Group controlId="addCompany">
              <Form.Label>Company Name*</Form.Label>
              <Form.Control
                name="company_name"
                type="text"
                value={myForm.company_name}
                onChange={(e) => {
                  handleChange(e);
                  handleInput(e);
                }}
                isInvalid={!!errors.company_name}
              />
              <Form.Control.Feedback type="invalid">
                {errors.company_name}
              </Form.Control.Feedback>
            </Form.Group>

            <div className="step-progress-btn">
              <Button variant="primary" onClick={() => validateForm()}>
                Validate
              </Button>
            </div>
          </Form>
        )}
      </Formik>
    );
  }

  return <div>Step1Form()</div>;
}

Upvotes: 1

DavidP
DavidP

Reputation: 2028

Your custom onChange={handleInput} function never passes the value to Formik.

Formik internally keeps track of your form values, so you don't need to add it using the useState method like you are now (const [myForm, setMyForm] = useState({});).

When you add a custom onChange to your form, you change your component state, while Formik's state never updates, so Yup does not have a value to validate.

If you add this just below your closing </Form> tag, you will see Formik never reads your form's updated values:

<pre>
  {JSON.stringify(
    {
      touched,
      isValid,
      isInvalid,
      errors,
      handleBlur,
      handleChange,
      values,
      validateForm
    },
    null,
    2
  )}
</pre>

Upvotes: 1

Related Questions