Published:

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

 


Subscribe or Follow Me For Updates

Subscribe to my YouTube channel or follow me on Twitter, Facebook or GitHub to be notified when I post new content.

Other than coding...

I'm currently attempting to travel around Australia by motorcycle with my wife Tina on a pair of Royal Enfield Himalayans. You can follow our adventures on YouTube, Instagram and Facebook.


Need Some React Hook Form Help?

Search fiverr to find help quickly from experienced React Hook Form developers.



Supported by