Yup dataURI validation

Viewed 2352

I have Field for img in my Formik-form (React), which could be link or dataURI

How to check with Yup that a valid value is entered in the Field?

Now I use:

const validationSchema = Yup.object().shape({
    img_url: Yup.string().url(),
  });

But it gives an error if dataURI is entered

1 Answers

There's no way to specify schema as one of two types: https://github.com/jquense/yup/issues/321

However you can dynamically return a schema with Yup.lazy(): https://github.com/jquense/yup/issues/647. If the img_url begins with 'data', return schema for data URI using Yup.string().matches(), otherwise, return schema for url with Yup.string().url()

You can find the gist and discussion about data URI regex here

This should work:

  const validationSchema = Yup.object().shape({
    img_url: Yup.lazy((value) =>
        /^data/.test(value)
          ? Yup.string()
              .trim()
              .matches(
                /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)$/i,
                'Must be a valid data URI',
              )
              .required()
          : Yup.string().trim().url('Must be a valid URL').required(),
      ),
  });

Note: I've added trim() so that you can have extra whitespaces around the URL or the data URI for img_url to still be considered valid. Also, I made img_url required so that it is considered invalid if empty. You might or might not want this based on your use case.

Here's a version without trim() or required():

validationSchema={Yup.object({
      img_url: Yup.lazy((value) =>
        /^data/.test(value)
          ? Yup.string().matches(
              /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)$/i,
              'Must be a valid data URI',
            )
          : Yup.string().url('Must be a valid URL'),
      )
Related