Skip to content

getFieldState

Get validation and interaction state of a specific field.

</> getFieldState: UseFormGetFieldState Since v7.25.0

This method returns individual field state. It is useful for retrieving nested field state in a type-safe way.

Props


NameTypeDescription
namestringregistered field name.
formStateobjectThis is an optional prop, which is only required if formState has not been read from or subscribed to via useForm, useFormContext or useFormState. See the rules below for more information.

Return


NameTypeDescription
isDirtybooleanfield is modified.
Condition: subscribe to dirtyFields.
isTouchedbooleanfield has received a focus and blur event.
Condition: subscribe to touchedFields.
invalidbooleanfield is not valid.
Condition: subscribe to errors.
isValidatingbooleanSince v7.51.0 field is currently being validated.
Condition: subscribe to isValidating.
errorundefined | FieldErrorfield error object.
Condition: subscribe to errors.
RULES
  • The prop must match a registered field name.
    register("test") // registers the input
    getFieldState("test") // ✅ returns state for the registered field
    getFieldState("non-existent-name") // ❌ returns default/false state since this name was never registered
  • getFieldState works by subscribing to form state updates, and you can subscribe to the formState in the following ways:
    • You can subscribe at the useForm, useFormContext or useFormState. This is will establish the form state subscription and getFieldState second argument will no longer be required.

      const {
      register,
      formState: { isDirty },
      } = useForm()
      register("test")
      getFieldState("test") // ✅
      const { isDirty } = useFormState()
      register("test")
      getFieldState("test") // ✅
      const {
      register,
      formState: { isDirty },
      } = useFormContext()
      register("test")
      getFieldState("test") // ✅
    • When form state subscription is not set up, you can pass the entire formState as the second optional argument by following the example below:

      const { register } = useForm()
      register("test")
      const { isDirty } = getFieldState("test") // ❌ formState isDirty is not subscribed at useForm
      const { register, formState } = useForm()
      const { isDirty } = getFieldState("test", formState) // ✅ formState.isDirty subscribed
      const { formState } = useFormContext()
      const { isTouched } = getFieldState("test", formState) // ✅ formState.touchedFields subscribed

Examples


import { useForm } from "react-hook-form"
export default function App() {
const {
register,
getFieldState,
formState: { isDirty, isValid },
} = useForm({
mode: "onChange",
defaultValues: {
firstName: "",
},
})
// you can invoke before render or within the render function
const fieldState = getFieldState("firstName")
return (
<form>
<input {...register("firstName", { required: true })} />{" "}
<p>{getFieldState("firstName").isDirty && "dirty"}</p>{" "}
<p>{getFieldState("firstName").isTouched && "touched"}</p>
<button
type="button"
onClick={() => console.log(getFieldState("firstName"))}
>
field state
</button>
</form>
)
}

Tips


  • In a reusable field component, subscribe to only that field with useFormState({ name }), and pass the result to getFieldState. The component then re-renders only when that field's state changes:

    function FieldError({ name }) {
    const { getFieldState } = useFormContext()
    const formState = useFormState({ name })
    const { error, isTouched } = getFieldState(name, formState)
    return isTouched && error ? <p role="alert">{error.message}</p> : null
    }
  • getFieldState is typed against your form values, so a misspelled nested path is a type error. Reading errors.some.deep.path by hand is not checked in the same way.