Skip to content

useWatch

React Hook for subscribing to input changes

</> useWatch: ({ control?: Control, name?: string, defaultValue?: unknown, disabled?: boolean }) => object

Behaves similarly to the watch API, however, this will isolate re-rendering at the custom hook level and potentially result in better performance for your application.

Props


NameTypeDescription
namestring | string[] | undefinedName of the field.
controlObjectcontrol object provided by useForm. It's optional if you are using FormProvider.
defaultValueunknowndefault value for useWatch to return before the initial render.

Note: the first render will always return defaultValue when it's supplied.
disabledboolean = falseOption to disable the subscription.
exactboolean = falseThis prop will enable an exact match for input name subscriptions.

Return


ExampleReturn
useWatch({ name: 'inputName' })unknown
useWatch({ name: ['inputName1'] })unknown[]
useWatch(){[key:string]: unknown}
RULES
  • The initial return value from useWatch will always return what's inside of defaultValue or defaultValues from useForm.

  • The only difference between useWatch and watch is at the root (useForm) level or the custom hook level update.

  • useWatch's execution order matters, which means if you update a form value before the subscription is in place, then the value updated will be ignored.

    setValue("test", "data")
    useWatch({ name: "test" }) // ❌ subscription is happened after value update, no update received
    useWatch({ name: "example" }) // ✅ input value update will be received and trigger re-render
    setValue("example", "data")

    You can overcome the above issue with a simple custom hook as below:

    const useFormValues = () => {
    const { getValues } = useFormContext()
    return {
    ...useWatch(), // subscribe to form value updates
    ...getValues(), // always merge with latest form values
    }
    }
  • useWatch's result is optimised for render phase instead of useEffect's deps, to detect value updates you may want to use an external custom hook for value comparison.

Examples:


Form

import React from "react"
import { useForm, useWatch } from "react-hook-form"
interface FormInputs {
firstName: string
lastName: string
}
function FirstNameWatched({ control }: { control: Control<FormInputs> }) {
const firstName = useWatch({
control,
name: "firstName", // without supply name will watch the entire form, or ['firstName', 'lastName'] to watch both
defaultValue: "default", // default value before the render
})
return <p>Watch: {firstName}</p> // only re-render at the custom hook level, when firstName changes
}
function App() {
const { register, control, handleSubmit } = useForm<FormInputs>()
const onSubmit = (data: FormInputs) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>First Name:</label>
<input {...register("firstName")} />
<input {...register("lastName")} />
<input type="submit" />
<FirstNameWatched control={control} />
</form>
)
}
import React from "react"
import { useForm, useWatch } from "react-hook-form"
function Child({ control }) {
const firstName = useWatch({
control,
name: "firstName",
})
return <p>Watch: {firstName}</p>
}
function App() {
const { register, control } = useForm({
defaultValues: {
firstName: "test",
},
})
return (
<form>
<input {...register("firstName")} />
<Child control={control} />
</form>
)
}

Advanced Field Array

import React from "react"
import { useWatch } from "react-hook-form"
function totalCal(results) {
let totalValue = 0
for (const key in results) {
for (const value in results[key]) {
if (typeof results[key][value] === "string") {
const output = parseInt(results[key][value], 10)
totalValue = totalValue + (Number.isNaN(output) ? 0 : output)
} else {
totalValue = totalValue + totalCal(results[key][value], totalValue)
}
}
}
return totalValue
}
export const Calc = ({ control, setValue }) => {
const results = useWatch({ control, name: "test" })
const output = totalCal(results)
// isolated re-render to calc the result with Field Array
console.log(results)
setValue("total", output)
return <p>{output}</p>
}

Thank you for your support

If you find React Hook Form to be useful in your project, please consider to star and support it.