Skip to content

ErrorMessage

Render validation error messages for a field.

</> ErrorMessage: Component Since v7.88.0

A simple component to render associated input's error message. Reads from the control prop when supplied, otherwise from the nearest FormProvider.

Props


NameTypeRequiredDescription
namestring✓Name of the field, or a global error path (root or root.*).
controlControlcontrol object provided by useForm. Optional if you are using FormProvider.
asReact.ElementTypeWrapper component or HTML tag. For example: as="span" or as={Text}
render({ message: string, messages?: Object}) => React.ReactNodeThis is a render prop for rendering error message or messages.

Note: you need to set criteriaMode to 'all' for using messages.

Examples


Single Error Message

import { useForm, ErrorMessage } from "react-hook-form"
interface FormInputs {
singleErrorInput: string
}
export default function App() {
const { register, control, handleSubmit } = useForm<FormInputs>()
const onSubmit = (data: FormInputs) => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register("singleErrorInput", { required: "This is required." })}
/>
<ErrorMessage control={control} name="singleErrorInput" />
<ErrorMessage
control={control}
name="singleErrorInput"
render={({ message }) => <p>{message}</p>}
/>
<input type="submit" />
</form>
)
}

Multiple Error Messages

import { useForm, ErrorMessage } from "react-hook-form"
interface FormInputs {
multipleErrorInput: string
}
export default function App() {
const { register, control, handleSubmit } = useForm<FormInputs>({
criteriaMode: "all",
})
const onSubmit = (data: FormInputs) => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register("multipleErrorInput", {
required: "This is required.",
pattern: {
value: /\d+/,
message: "This input is number only.",
},
maxLength: {
value: 10,
message: "This input exceed maxLength.",
},
})}
/>
<ErrorMessage
control={control}
name="multipleErrorInput"
render={({ messages }) =>
messages &&
Object.entries(messages).map(([type, message]) => (
<p key={type}>{message}</p>
))
}
/>
<input type="submit" />
</form>
)
}

With FormProvider

import { useForm, FormProvider, ErrorMessage } from "react-hook-form"
function Field() {
return <ErrorMessage name="singleErrorInput" />
}
export default function App() {
const methods = useForm()
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit((data) => console.log(data))}>
<input
{...methods.register("singleErrorInput", {
required: "This is required.",
})}
/>
<Field />
<input type="submit" />
</form>
</FormProvider>
)
}

Tips


  • as only wraps the message text and does not receive other props. To add a class name, an id for aria-describedby, or role="alert", use render:

    <ErrorMessage
    name="email"
    render={({ message }) => (
    <p id="email-error" role="alert" className="field-error">
    {message}
    </p>
    )}
    />
  • Each ErrorMessage subscribes only to the errors for its name, so you can use many of them without re-rendering the whole form.

  • Use name="root.server" to show the error set by the Form component, or any root error you set with setError.

Troubleshooting


The field is invalid but ErrorMessage renders nothing

Why it happens

The validation rule may not include a message. For example, required: true creates an error without display text, so the default renderer has nothing to show.

Fix

Give each rule a message, or use render to provide a fallback:

<input {...register("email", { required: "Email is required" })} />
<ErrorMessage
name="email"
render={({ message }) => <p role="alert">{message || "Invalid value"}</p>}
/>

messages is undefined in the render prop

Why it happens

React Hook Form stores all failed rules in messages only when the form uses criteriaMode: "all". The default mode keeps the first relevant error.

Fix

Initialize the form with useForm({ criteriaMode: "all" }), or render the single message value instead.

ErrorMessage cannot find the form control

Why it happens

No control prop was passed and the component is outside a FormProvider.

Fix

Pass control from useForm, or place ErrorMessage inside <FormProvider {...methods}>.