react-hook-form handling server-side errors in handleSubmit react-hook-form handling server-side errors in handleSubmit reactjs reactjs

react-hook-form handling server-side errors in handleSubmit


In order to display the error from the server to your user, you need to use:

  • setError to set the error programmatically when the server returns an error response.
  • errors to get the error state of every fields in your form to display to the user.
type FormInputs = {  username: string;};const { setError, formState: { errors } } = useForm<FormInputs>();

In your handleSubmit callback

axios  .post(url, data)  .then((response) => {    alert("Login successful");  })  .catch((e) => {    const errors = e.response.data;    if (errors.username) {      setError('username', {        type: "server",        message: 'Something went wrong with username',      });    }    if (errors.password) {      setError('password', {        type: "server",        message: 'Something went wrong with password',      });    }  });

In your component

<label htmlFor="username">username</label><input id="username" {...register("username")} /><div>{errors.username && errors.username.message}</div>

Live Demo

Edit 64469861/react-hook-form-handling-errors-in-handlesubmit


Inspired by @NearHuscarl's answer, I've done the following hack s.t. changes in either the username or the password inputs will remove the single error.

This hack does not scale well if your error is related to multiple fields in the form, but it worked for the login use case.

onSubmit:

const onSubmit = handleSubmit(async (data) => {    const url = '/auth/local'    const [err, userLoginResult] = await to<AxiosResponse>(axios.post(url, data)) // see await-to-js     if (userLoginResult) {      alert('Login successful')    }    else if (err) {      const formError = { type: "server", message: "Username or Password Incorrect" }      // set same error in both:      setError('password', formError)      setError('username', formError)    }  })

component:

  return (    <div className="RegisterOrLogIn">      <form onSubmit={onSubmit}>        <div>          <label htmlFor="username">username</label>          <input name="username" id="username" ref={register} />        </div>        <div>          <label htmlFor="password">Password</label>          <input type="password" id="password" name="password" ref={register} />        </div>        <div>{errors.username && errors.password?.message /*note the cross check*/}</div>        <button type="submit"> </button>      </form>    </div>  )

by setting and rendering the error on both errors.password & errors.username, the error will disappear when the user updates either of those fields.