Published: September 13 2021

React Hook Form - Display custom error message returned from API request

Tutorial built with React 17.0.2 and React Hook Form 7.15.0

This is a quick example of how to display a custom error message on a React Hook Form that is returned from an HTTP API request.

The below code snippets are from a React + Recoil auth tutorial I posted recently, to see the code running in a live demo app check out React + Recoil - Basic HTTP Authentication Tutorial & Example.


React Hook Form Component with Custom API Error

Path: /src/login/Login.jsx

The login page contains a form built with the React Hook Form library that contains username and password fields for logging into the React app.

Set error after failed HTTP request

The onSubmit function gets called when the form is submitted and valid, and posts the user credentials to the api by calling userActions.login(). If the api request fails the .catch() method is executed, which calls the React Hook Form setError() function with a name ('apiError') and an error object containing the message ({ message: error }). The setError() function adds the error to the formState.errors object which is then rendered at the bottom of the React Hook Form in the returned JSX template ({errors.apiError && ...).

import { useForm } from "react-hook-form";
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';

import { useUserActions } from '_actions';

export { Login };

function Login() {
    const userActions = useUserActions();

    // form validation rules 
    const validationSchema = Yup.object().shape({
        username: Yup.string().required('Username is required'),
        password: Yup.string().required('Password is required')
    const formOptions = { resolver: yupResolver(validationSchema) };

    // get functions to build form with useForm() hook
    const { register, handleSubmit, setError, formState } = useForm(formOptions);
    const { errors, isSubmitting } = formState;

    function onSubmit({ username, password }) {
        return userActions.login(username, password)
            .catch(error => {
                setError('apiError', { message: error });

    return (
        <div className="col-md-6 offset-md-3 mt-5">
            <div className="alert alert-info">
                Username: test<br />
                Password: test
            <div className="card">
                <h4 className="card-header">Login</h4>
                <div className="card-body">
                    <form onSubmit={handleSubmit(onSubmit)}>
                        <div className="form-group">
                            <input name="username" type="text" {...register('username')} className={`form-control ${errors.username ? 'is-invalid' : ''}`} />
                            <div className="invalid-feedback">{errors.username?.message}</div>
                        <div className="form-group">
                            <input name="password" type="password" {...register('password')} className={`form-control ${errors.password ? 'is-invalid' : ''}`} />
                            <div className="invalid-feedback">{errors.password?.message}</div>
                        <button disabled={isSubmitting} className="btn btn-primary">
                            {isSubmitting && <span className="spinner-border spinner-border-sm mr-1"></span>}
                        {errors.apiError &&
                            <div className="alert alert-danger mt-3 mb-0">{errors.apiError?.message}</div>


Need Some React Hook Form Help?

Search fiverr for freelance React Hook Form developers.

Follow me for updates

On Twitter or RSS.

When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Supported by