React-hook-form: Yup: error not displaying in ErrorMessage when validating an Array of Strings

Created on 18 Feb 2020  路  3Comments  路  Source: react-hook-form/react-hook-form

Describe the bug
the error message thrown by Yup for an email array field does not show up in ErrorMessage.

To Reproduce

  1. Setup a Yup Schema for a recipients field defined as an Array comprised of string emails and required
  2. Register the schema as ValidationSchema option for useForm
  3. Register the input element for that recipients
  4. Fill in the Recipients field incorrectly but see no error message displaying

Codesandbox link
https://codesandbox.io/s/kind-lamport-vopi4

Expected behavior
error.message being passed to ErrorMessage and displaying.

Screenshots
image
As shown above, the message object passed by ErrorMessage for Recipients shows both Message and Messages property as undefined. Hence, no error is displayed.
message isn't passed down from ValidationError to the errors object.

Desktop (please complete the following information):

  • OS: [Windows 8.1]
  • Browser [Chrome]
  • Version [Version 80]

Additional context
Prior to validating recipientList as an Array of Emails, I applied a transform to comma delimited string from the Recipients input into an array of emails to match against.

const surveyFormSchema = object().shape({
  subject: string().required(),
  body: string().required(),
  recipientList: array()
    // This transforms a comma delimited string into an array of emails
    // and then performs email validation on each one.
    .transform(function(value, originalValue) {
      if (this.isType(value) && value !== null) {
        return value;
      }
      return originalValue ? originalValue.split(/[\s,]+/) : [];
    })
    .required("At least one email is required")
    .of(string().email(({ value }) => `${value} is an invalid email.`))
});

After console logging, the errors object from useForm, I see that errors[recipientList] is an Array of 1 instead of being an object like errors[subject] and errors[body].
errors[recipientList][0] does give back an object with the right message.
Any idea why it becomes an Array instead of staying as an Object?

question

Most helpful comment

Ah, I see why now.

To answer my own question, I solved it by checking for whether error[name] isArray(), then map it to a list of p elements

<input name={name} ref={register} />
{error[name] && error[name].map(({message}) => {
  return <p>{message}</p>
})}

_should probably wrap the above in ul and li (provide keys as well)._

To not take too much space, I instead returned the value in the yup schema

const schema = object.shape({
  ...
  list: array().of(string().email(({value}) => value)
})

then join the error'ed entries into a single string

const customErrorMessage = () => errors[name].map(({message}) => message).join(', ') + ' are invalid emails.'
...
return (
  <>
    <input name={name} ref={register} />
    {errors[name] && <p>{customErrorMessage()}</p>
  </>
)

All 3 comments

recipientList: array()
    // This transforms a comma delimited string into an array of emails
    // and then performs email validation on each one.
    .transform(function(value, originalValue) {
      if (this.isType(value) && value !== null) {
        return value;
      }
      return originalValue ? originalValue.split(/[\s,]+/) : [];
    })
    .required("At least one email is required")
    .of(string().email(({ value }) => `${value} is an invalid email.`))

because you r return array right?

Ah, I see why now.

To answer my own question, I solved it by checking for whether error[name] isArray(), then map it to a list of p elements

<input name={name} ref={register} />
{error[name] && error[name].map(({message}) => {
  return <p>{message}</p>
})}

_should probably wrap the above in ul and li (provide keys as well)._

To not take too much space, I instead returned the value in the yup schema

const schema = object.shape({
  ...
  list: array().of(string().email(({value}) => value)
})

then join the error'ed entries into a single string

const customErrorMessage = () => errors[name].map(({message}) => message).join(', ') + ' are invalid emails.'
...
return (
  <>
    <input name={name} ref={register} />
    {errors[name] && <p>{customErrorMessage()}</p>
  </>
)

awesome glad you work it out :)

Was this page helpful?
0 / 5 - 0 ratings