react-hook-form: Ability to scroll to the input with error

It would be nice to have some scrollToError method which would scroll to the highest input found which name matches one of the errors keys.

Currently, there is a similar behavior that happens after the form validation but there are cases when errors are set manually for some fields using setError API, for example, after server’s error response.

I believe I could implement such functionality outside RHF but I’d have to store input refs and names separately for this and it just feels like it would be much better if it was implemented in RHF.

Or perhaps, alternatively, if I could access all input refs mapped to fields names from RHF it would make it simpler to implement such scrolling functionality manually.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 2
  • Comments: 48 (23 by maintainers)

Most upvoted comments

Here’s one that scrolls to the top-most input:

const elements = Object.keys(errors).map(name => document.getElementsByName(name)[0]).filter(el => !!el);
elements.sort((a, b) => b.scrollHeight - a.scrollHeight);
elements[0]?.scrollIntoView({behavior: 'smooth', block: 'center'});

One thing I have noticed is errors are not in order they are registered but alphabetical. So the first ref that you scroll to may not be the top-most. I’m not sure how one would go about doing that.

function useScrollToError(errors) {
  useEffect(() => {
    for(const error of Object.values(errors)) {
      if(error?.ref) {
        error.ref.scrollIntoView({ behavior: 'smooth' })
        break
      }
    }
  }, [errors])
}

can anyone share his workaround if it’s done?

function useScrollToError(errors) {
  useEffect(() => {
    const errorsvalues = Object.values(errors)
    if (errorsvalues.length > 0) {
      errorsvalues[0].ref.scrollIntoView({ behavior: 'smooth' })
    }
  }, [errors])
}

Thanks @vensauro setFocus is coming, maybe it will be helpful?

@bluebill1049 awesome, much appreciated ❤️

Is anyone already working on this? I would love to work on this if it’s available.

I actually used to expose ref for error inputs. Let me think about this, see if it’s a good idea to embed in RHF or some alternative solution.

Here’s one that scrolls to the top-most input:

const elements = Object.keys(errors).map(name => document.getElementsByName(name)[0]).filter(el => !!el);
elements.sort((a, b) => b.scrollHeight - a.scrollHeight);
elements[0]?.scrollIntoView({behavior: 'smooth', block: 'center'});

Thanks for sharing. I don’t know why, but for me, a.scrollHeight - b.scrollHeight is the correct thing (not b-a). Maybe because my layout is RTL.

Yes, this is for v7, but can be done for v6,

and i used a enhanced version of this in v7:

function useScrollToError(errors) {
  useEffect(() => {
    for(const error of Object.values(errors)) {
      if(error?.ref) {
        error.ref.scrollIntoView({ behavior: 'smooth' })
        break
      }
    }
  }, [errors])
}

on v6, if using controller, you can use the focus like this:

 React.useEffect(() => {
    if (errors.firstName) errors.firstName.ref.focus();
  }, [errors]);

or you can customize the input, making a shared ref and put an onFocus function on the controller, that make the scroll for the ref, you can pick the ref from the render method, or from the useController return, if you use this ref, this ref will be the html element

no one is working on it just yet, i think the idea is to expose errors object with ref. so you can do a scrollIntoView and then focus().

errors.firstName.ref.scrollntoView();

// then errors.firstName.ref.focus();

I think we can expose the ref in the errors object, and let user to do the scroll into the view or any other other stuff.