简体   繁体   中英

Yup 'notRequired' method doesn't seem to be working in my form validation

I am using Yup to validate my form fields.

I want the user to paste their instagram URL into the input field. It is not a required field but if they do start to type, the string must match the regex. The regex works, however the 'invalid url' message still displays if the user doesn't type anything, even although the field should not be required. I have tried the following but it still doesn't work. Any suggestions?

 const validationSchema = Yup.object().shape({
    instagram: Yup.string()
      .notRequired()
      .matches(
        /(?:(?:http|https):\/\/)?(?:www.)?(?:instagram.com|instagr.am)\/([A-Za-z0-9-_]+)/im,
        'invalid url'
      ),
  });

In this case you need to use the .nullable() method.

Try this :

 const validationSchema = Yup.object().shape({
    instagram: Yup.string()
      .matches(
        /(?:(?:http|https):\/\/)?(?:www.)?(?:instagram.com|instagr.am)\/([A-Za-z0-9-_]+)/im,
        'invalid url'
      )
      .nullable(),
  });

Long time no see! I'm not sure if you're using a form state manager or not, but a lot of people seem to use Formik with Yup.

Take a look at this working example using Formik with Yup :

用 Yup 编辑 Formik

Demo Code :

import * as React from "react";
import { Formik } from "formik";
import * as Yup from "yup";

const validationSchema = Yup.object().shape({
  instagram: Yup.string()
    .notRequired()
    .matches(
      /(?:(?:http|https):\/\/)?(?:www.)?(?:instagram.com|instagr.am)\/([A-Za-z0-9-_]+)/im,
      "Invalid Instagram URL. Example: http(s)://instagram.com/janedoe"
    )
});

const ValidatedInstagramForm = () => {
  const handleFormSubmit = (values, { setSubmitting }) => {
    alert(
      `Validated form was submitted with:\n${JSON.stringify(values, null, 4)}`
    );
    setSubmitting(false);
  };

  return (
    <Formik
      initialValues={{ instagram: "" }}
      onSubmit={handleFormSubmit}
      validationSchema={validationSchema}
    >
      {({
        errors,
        handleBlur,
        handleChange,
        handleSubmit,
        isSubmitting,
        values,
        touched
      }) => (
        <form className="form" onSubmit={handleSubmit}>
          <div className="input-container">
            <label className="label" htmlFor="instagram">
              Instagram
            </label>
            <input
              name="instagram"
              type="text"
              placeholder="Enter your instagram (optional)..."
              value={values.instagram}
              onChange={handleChange}
              onBlur={handleBlur}
              className="input"
              style={{
                background:
                  errors.instagram && touched.instagram
                    ? "rgba(255, 0, 0, 0.25)"
                    : "",
                borderColor: errors.instagram && touched.instagram ? "red" : ""
              }}
            />
            {errors.instagram && touched.instagram && (
              <div className="error">{errors.instagram}</div>
            )}
          </div>
          <button className="button" type="submit" disabled={isSubmitting}>
            Submit
          </button>
        </form>
      )}
    </Formik>
  );
};

export default ValidatedInstagramForm;

If you're not using a form state manager, then you could always manually validate the input on form submit instead of on input change:

编辑手动验证输入

Demo Code :

import * as React from "react";

const ValidatedInstagramForm = () => {
  const [value, setValue] = React.useState("");
  const [error, setError] = React.useState("");

  const handleChange = ({ target: { value } }) => {
    setValue(value);
    setError("");
  };

  const isValidInput = (value) => {
    if (!value) return "";

    return /(?:(?:http|https):\/\/)?(?:www.)?(?:instagram.com|instagr.am)\/([A-Za-z0-9-_]+)/im.test(
      value
    )
      ? ""
      : "Invalid Instagram URL. Example: http(s)://instagram.com/janedoe";
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    const error = isValidInput(value);

    if (!error)
      alert(
        `Validated form was submitted with:\n${JSON.stringify(
          { instagram: value },
          null,
          4
        )}`
      );
    else setError(error);
  };

  return (
    <form className="form" onSubmit={handleSubmit}>
      <div className="input-container">
        <label className="label" htmlFor="instagram">
          Instagram
        </label>
        <input
          name="instagram"
          type="text"
          placeholder="Enter your instagram (optional)..."
          value={value}
          onChange={handleChange}
          className="input"
          style={{
            background: value && error ? "rgba(255, 0, 0, 0.25)" : "",
            borderColor: value && error ? "red" : ""
          }}
        />
        {value && error ? <div className="error">{error}</div> : null}
      </div>
      <button className="button" type="submit" disabled={error}>
        Submit
      </button>
    </form>
  );
};

export default ValidatedInstagramForm;

In fact, there are two definitions of .matches()<\/code> method :

  • Here is the correct code (you don't need to include .notRequired<\/code> method) :

I had several problems in this matter, so this is my take, and solution. eg Allowed null, or if they were filled in then they had to have an min length.

    taxid: Yup.string()
      .nullable()
      .notRequired()
      .transform(x => x === '' ? undefined : x)
      .min(5, 'TaxID must be at least 5 characters'),
    corpname: Yup.string()
      .nullable()
      .notRequired()
      .transform(x => x === '' ? undefined : x)
      .min(2, 'Company name must be at least 2 characters'),
    postno: Yup.string()
        .required('Post number is required')
        .min(4, 'Post number must be at least 4 characters'),

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM