react-hook-form: `errors` structure and type mismatch

Describe the bug The errors structure does not match the typing when using a array value.

Our form values structure:

type FormValues = {
	emails: string[]
}

Our form hook looks like:

const { register, errors, handleSubmit, reset } = useForm<FormValues>)()

This results in errors structure of:

{
	"emails[0]": "asdf@gmail.com",
	"emails[1]": "asdf2@gmail.com"
}

where the errors typing is expecting it to be more like:

{
	"emails": ["asdf@gmail.com", "asdf2@gmail.com"]
}

Expected behavior errors should match the values structure or errors typings should be updated to match the structure it is providing.

Screenshots image

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 3
  • Comments: 18 (18 by maintainers)

Most upvoted comments

I guess before I go too deep in this, can I ask why these errors needs to be strings instead of a consistent error object where the string is a message and the type is “ValidationError”?

Then it wouldn’t need this odd difference.

Since this is a new feature (Correct me if I’m wrong), seems better just to make that a consistent output

Go for it

Sounds good! I will be testing it out as soon as you release it and can hopefully provide feedback on it fairly quickly.

Thanks, @stramel I will sort out #134 then come back to this issue. @barry4dev I may need some help over this type issue 🙏

@barrymay I will create a PR on this and add you to review.

@barrymay I agree, I will look into a fix tmr.

Hi guys - I’m actually having a problem with this change (really is the one from https://github.com/bluebill1049/react-hook-form/issues/136 but this is linked to it). I’m fine if ValidationSchema always return strings as errors, but then the object should enforce that typing wise. I should have tested the latest against my app, but now I see it.

I’ll see if I can make a change.

That would be great 🙏 thanks heaps for your help @stramel really grateful. ❤️

yea keep it as flattened for now.

That looks great @bluebill1049! I’m assuming that for now you are keeping the errors as the flattened structure?

FYI: (coming feature update, should solve defaultValues issue)

watch API update:

  1. watch return default value change: watch(['test', 'test1']) // deafult value return [undefined, undefined] instead of undefined watch() // default value return {} instead of undefined

  2. watch integrate with defaultValues watch will inherit from data in defaultValues, but watch function arguments remain unchanged. second argument defaultValue will overwrite data in defaultValues which set up in useForm()

  3. watch now support nested object look up eg

  const data = watch('test');
  console.log(data);

    <form>
      <input name="test[0]" ref={register} />
      <input name="test[1]" ref={register} />
    </form>

this above example will watch both test[0] and test[1]

defaultValues update:

defaultValues now support nested object, eg:

const { register } = useForm({
  defaultValues: { test: {data: [1, 2]}},
})

getValues update:

getValues now support nest argument to return data in a nested format, eg:

getValues(); // {'test[0]': 1, 'test[1]': 2}
getValues({ nest: true }); // {test: [1,2]}

@bluebill1049 WRT the 2 options, those are the 2 options that I came to as well when thinking about it.

When I was thinking of the solution my initial thought was option 2. As a developer of a form, I have a data structure in mind and logically it would make sense to me to refer to the values and errors using a similar structure.

When you start to think about “Nested Fields”, it really depends if you are using object or array notation as to which way is easier.

I generally move my inputs into a component that handles displaying of the errors associated with the input. When thinking about accessing the errors this way, option 1 seems to make more sense as arrays could complicate option 2.

However, I feel that defaultValues should use the expected structure (option 2). Generally, the defaultValues will be a copy of what was submitted to the server. And requiring a transform of the data before passing it through to defaultValues feels incorrect.

Perhaps anything dealing with the values should be option 2 and errors should be option 1? Or similar to what you mentioned in #134, where we provide options at the useForm hook to choose flatten?