Skip to content

useWatch

React Hook for subscribe to input changes

useWatch: ({ control?: Control, name?: string, defaultValue?: any }) => object

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

Props

NameTypeDescription
namestring | string[]Name of the field.
controlObjectcontrol object provided by useForm. It's optional if you are using FormContext.
defaultValueanydefault value for useWatch to return before the initial render.
import React from "react";
import { useForm, useWatch } from "react-hook-form";

function IsolateReRender({ control }) {
  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 <div>{firstName}</div>; // only re-render at the component level, when firstName changes
}

function App() {
  const { register, control, handleSubmit } = useForm();
  
  return (
    <form onSubmit={handleSubmit(data => console.log("data", data))}>
      <input {...register("firstName")} />
      <input {...register("last")} />
      <IsolateReRender control={control} />
      
      <input type="submit" />
    </form>
  );
}
import React from "react";
import { useForm, useWatch } from "react-hook-form";

interface FormInputs {
  firstName: 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 component 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 type="submit" />
      <FirstNameWatched control={control} />
    </form>
  );
}
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>;
};

Tips

  • The initial return value from useWatch will always return what's inside of defaultValue or defaultValues from useForm.

  • The only different between useWatch and watch is at root level or component level update.
Edit