</> useWatch: (UseWatchProps) => object
Behaves similarly to the watch API; however, it isolates re-rendering at the custom hook level, which can result in better performance for your application.
Props
| Name | Type | Description |
|---|---|---|
name | string | string[] | undefined | Name of the field. Reactive — changing this prop dynamically will update the subscription to the new field name. |
control | Object | control object provided by useForm. It's optional if you are using FormProvider. |
compute | function | Since v7.61.0 Subscribe to selective and computed form values.
|
defaultValue | unknown | Fallback value returned before the form has mounted and no current value exists yet. Once the form is mounted, the actual current form value takes precedence over this fallback. |
disabled | boolean = false | Since v7.13.0 Option to disable the subscription. |
exact | boolean = false | Since v7.20.0 Enable exact name matching. When false (default), a subscription fires when the subscribed name is a prefix of the changed field name, or vice versa (for example, subscribing to "users" receives updates for "users.0.name"). Since v7.81.0 When true, the subscription fires when the subscribed field itself or one of its ancestor paths is updated (for example, subscribing to "users.0.name" receives updates when "users.0" or "users" is set via setValue), but not when a nested child path changes (subscribing to "users" does not receive updates for "users.0.name"). |
Return
| Example | Return |
|---|---|
useWatch({ name: 'inputName' }) | unknown |
useWatch({ name: ['inputName1'] }) | unknown[] |
useWatch() | {[key:string]: unknown} |
-
On initial render,
useWatchreturns the current form value if available. ThedefaultValueprop (ordefaultValuesfromuseForm) is used only as a fallback before the form has mounted — i.e., before any values are registered. -
The only difference between
useWatchandwatchis at the root (useForm) level or the custom hook level. -
useWatch's execution order matters, which means if you update a form value before the subscription is in place, then the updated value will be ignored.setValue("test", "data")useWatch({ name: "test" }) // ❌ subscription happened after value update, no update receiveduseWatch({ name: "example" }) // ✅ input value update will be received and trigger re-rendersetValue("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 optimized for the render phase instead ofuseEffectdependencies. To detect value updates, you may want to use an external custom hook for value comparison.
Examples:
Form
import { useForm, useWatch } from "react-hook-form"interface FormInputs {firstName: stringlastName: 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 bothdefaultValue: "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>)}
Advanced Field Array
import { useWatch } from "react-hook-form"function totalCal(results) {let totalValue = 0for (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 Arrayconsole.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 starring and supporting it.