| | |

React Hook Form 09 ๐Ÿ“‹ Watching Values โ€” watch vs useWatch for selective subscriptions

โฑ๏ธ Estimated read: 15 min | |

The watch function and the useWatch hook read the same form values, but they subscribe at different scopes. The watch function is called on the useForm return object, and it triggers a re-render at the component that owns the useForm call. The useWatch hook is called inside a child component, and it triggers a re-render only at that child component. The values are identical; the difference is the render boundary, and the boundary is the mechanism that determines whether a keystroke in one field re-renders the whole form or only the display that reads that field.

The React Hook Form documentation states the distinction plainly: useWatch “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” . The FAQ adds the decision rule: watch re-renders “the component that calls useForm“, and useWatch re-renders “only the component that calls it” . The rule is simple: if the value is read in the component that owns the form, watch is convenient; if the value is read in a nested component, useWatch is the performance choice.

The library also exposes two subscription mechanisms that do not re-render at all. The getValues function reads the current values on demand, and it is the mechanism for the event handlers and the effects. The watch callback form (or the subscribe method) runs a callback on every change, and it is the mechanism for the autosave, the analytics, and the other side effects that do not need the component to re-render.

Key point: watch subscribes at the useForm level and re-renders the component that owns the form. useWatch subscribes at the component level and re-renders only the component that calls the hook. The values are the same; the difference is the render scope. The getValues function reads the values without a subscription, and the watch callback form (or the subscribe method) is for the side effects that do not need a re-render.


Why the two APIs exist

The render-scope problem. A form with a live total that updates as the user types needs to read the values during the render. If the total is rendered in the same component that owns the useForm call, the watch("items") call re-renders the whole form on every item change. If the total is extracted into a child component, the useWatch({ control, name: "items" }) call re-renders only the total component. The extraction is the mechanism that isolates the re-render, and the control prop is the connection between the child and the form.

The subscription-timing problem. The useWatch hook subscribes when the component mounts. If the value is set before the subscription is in place, the update is ignored. The documentation warns about this: setValue("test", "data") followed by useWatch({ name: "test" }) does not receive the update, because the subscription happened after the value change . The custom hook that merges useWatch() with getValues() is the workaround, because the getValues() provides the current value even when the subscription missed the update.

The side-effect problem. A form that autosaves or tracks analytics needs to react to the value changes without re-rendering. The watch callback form (or the subscribe method) is the mechanism: the callback runs on every change, and no component re-renders . The type argument in the callback distinguishes the user changes ("change") from the programmatic changes (undefined for setValue and reset), which is the mechanism that lets the autosave ignore the programmatic updates.

The React Compiler problem. The watch and the getValues return values keep the same reference across renders, and the React Compiler may cache the result and render the stale values. The documentation recommends the useWatch for the values that are rendered in the compiled components, and the subscribe for the side effects . The "use no memo" directive is the escape hatch for the component that must keep the watch call.

The derived-value problem. A total that depends on several fields re-renders on every change to any of the fields, even when the total does not change. The compute option (since v7.61.0) is the mechanism that re-renders only when the computed result changes, not on every keystroke . The compute function receives the watched value and returns the derived value, and the deep comparison is the mechanism that decides whether the re-render is needed.


a. The watch function and the form-level subscription

The watch function is the method on the useForm return object. It has the four overloads: the single field, the array of fields, the entire form, and the callback form.

// The watch function overloads
import { useForm } from "react-hook-form";

type CheckoutFormValues = {
  items: { price: number }[];
  coupon: string;
};

function CheckoutForm() {
  const { register, watch } = useForm<CheckoutFormValues>({
    defaultValues: { items: [], coupon: "" },
  });

  // The single field: re-renders the form on every change to coupon.
  const coupon = watch("coupon");

  // The array of fields: re-renders on every change to either field.
  const [items, couponValue] = watch(["items", "coupon"]);

  // The entire form: re-renders on every change to any field.
  const allValues = watch();

  return (
    <form>
      <input {...register("coupon")} />
      <p>Coupon: {coupon}</p>
    </form>
  );
}

The watch call in the component body is the render-level subscription. The component re-renders on every change to the watched fields, and the watch call returns the current value . The re-render scope is the component that owns the useForm call, which is the reason the watch in the render body of a large form is the performance problem.

The callback form is the subscription without the re-render. The callback receives the values and the { name, type } object, and the unsubscribe function is the cleanup.

// The callback form
import { useEffect } from "react";
import { useForm } from "react-hook-form";

function AutosaveForm() {
  const { register, watch } = useForm();

  useEffect(() => {
    const subscription = watch((values, { name, type }) => {
      // The type is "change" for the user input.
      // The type is undefined for the setValue and the reset.
      if (type === "change") {
        // The autosave runs without a re-render.
        console.log("Autosave:", values);
      }
    });

    return () => subscription.unsubscribe();
  }, [watch]);

  return <form><input {...register("name")} /></form>;
}

The type argument is the mechanism that distinguishes the user input from the programmatic change. The "change" is the user input, and the undefined is the setValue or the reset . The distinction is the mechanism that lets the autosave ignore the programmatic updates that would otherwise cause the redundant API calls.


b. The useWatch hook and the isolated subscription

The useWatch hook is called inside the child component, and it receives the control object from the useForm call. The hook returns the current value, and the child component re-renders only when the watched value changes.

// The useWatch hook
import { useForm, useWatch, type Control } from "react-hook-form";

function OrderTotal({ control }: { control: Control<CheckoutFormValues> }) {
  // The useWatch subscribes to the items field.
  // Only this component re-renders when items changes.
  const items = useWatch({ control, name: "items" });
  const coupon = useWatch({ control, name: "coupon" });

  const total = items.reduce((sum, item) => sum + item.price, 0);
  const discount = coupon === "SAVE10" ? total * 0.1 : 0;

  return <p>Total: ${total - discount}</p>;
}

function CheckoutForm() {
  const { register, control } = useForm<CheckoutFormValues>({
    defaultValues: { items: [], coupon: "" },
  });

  return (
    <form>
      <input {...register("coupon")} />
      {/* The OrderTotal re-renders, the CheckoutForm does not. */}
      <OrderTotal control={control} />
    </form>
  );
}

The control prop is the connection between the child and the form. The useWatch hook reads the values through the control object, and the child component re-renders only when the watched values change . The CheckoutForm component does not re-render on the keystrokes, which is the performance benefit.

The defaultValue option is the fallback before the form is mounted. The option is used only when the form has no current value, and the actual value takes precedence once the form is mounted .

// The defaultValue fallback
function NameDisplay({ control }: { control: Control<FormValues> }) {
  // The defaultValue is "Guest" before the form is mounted.
  // The actual value replaces it once the form is mounted.
  const name = useWatch({ control, name: "name", defaultValue: "Guest" });

  return <p>{name}</p>;
}

The exact option (since v7.20.0, with the behavior refined in v7.81.0) is the mechanism that controls the prefix matching. The default exact: false fires the subscription when the watched name is a prefix of the changed field, so the useWatch({ name: "users" }) receives the updates for the users.0.name . The exact: true is the mechanism that restricts the subscription to the exact field or the ancestor paths.

// The exact option
function UserCount({ control }: { control: Control<FormValues> }) {
  // The exact: true means the subscription fires when the users array
  // is set, but not when the users.0.name is set.
  const users = useWatch({ control, name: "users", exact: true });

  return <p>{users?.length ?? 0} users</p>;
}

The compute option (since v7.61.0) is the mechanism that re-renders only when the derived value changes. The function receives the watched value and returns the derived value, and the deep comparison is the mechanism that decides whether the re-render is needed .

// The compute option
function ItemCount({ control }: { control: Control<FormValues> }) {
  // The compute returns the item count.
  // The component re-renders only when the count changes,
  // not on every keystroke in the item name.
  const count = useWatch({
    control,
    name: "items",
    compute: (items = []) => items.length,
  });

  return <p>{count} items</p>;
}

The compute is the mechanism that reduces the re-render frequency from the every-keystroke to the value-change. The total that depends on several fields is the common case, and the compute is the mechanism that makes the total component re-render only when the total changes.


Complete Example Session

// ============================================
// PART 1: THE WATCH RE-RENDER SCOPE
// ============================================

import { useForm } from "react-hook-form";

function CheckoutForm() {
  const { register, watch } = useForm<CheckoutFormValues>({
    defaultValues: { items: [], coupon: "" },
  });

  // The watch in the form component re-renders the whole form.
  const coupon = watch("coupon");

  return (
    <form>
      <input {...register("coupon")} />
      <p>Coupon: {coupon}</p>
    </form>
  );
}

// ============================================
// PART 2: THE USEWATCH ISOLATED SCOPE
// ============================================

import { useWatch, type Control } from "react-hook-form";

function CouponDisplay({ control }: { control: Control<CheckoutFormValues> }) {
  // The useWatch re-renders only this component.
  const coupon = useWatch({ control, name: "coupon" });

  return <p>Coupon: {coupon}</p>;
}

function CheckoutForm() {
  const { register, control } = useForm<CheckoutFormValues>({
    defaultValues: { items: [], coupon: "" },
  });

  return (
    <form>
      <input {...register("coupon")} />
      {/* The CouponDisplay re-renders, the CheckoutForm does not. */}
      <CouponDisplay control={control} />
    </form>
  );
}

// ============================================
// PART 3: THE GETVALUES NO SUBSCRIPTION
// ============================================

function SubmitButton({ getValues }: { getValues: () => CheckoutFormValues }) {
  const handleClick = () => {
    // The getValues reads the current values without a subscription.
    const values = getValues();
    console.log(values.coupon);
  };

  return <button type="button" onClick={handleClick}>Log</button>;
}

// ============================================
// PART 4: THE SUBSCRIBE SIDE EFFECT
// ============================================

import { useEffect } from "react";

function AutosaveForm() {
  const { register, watch } = useForm();

  useEffect(() => {
    const subscription = watch((values, { name, type }) => {
      // The callback runs without a re-render.
      // The type is "change" for the user input.
      if (type === "change") {
        console.log("Autosave:", name, values[name!]);
      }
    });

    return () => subscription.unsubscribe();
  }, [watch]);

  return <form><input {...register("name")} /></form>;
}

// ============================================
// PART 5: THE DEFAULT VALUE FALLBACK
// ============================================

function NameDisplay({ control }: { control: Control<FormValues> }) {
  // The defaultValue is the fallback before the form is mounted.
  const name = useWatch({ control, name: "name", defaultValue: "Guest" });

  return <p>{name}</p>;
}

// ============================================
// PART 6: THE EXACT OPTION
// ============================================

function UserCount({ control }: { control: Control<FormValues> }) {
  // The exact: true restricts the subscription to the exact field.
  const users = useWatch({ control, name: "users", exact: true });

  return <p>{users?.length ?? 0} users</p>;
}

// ============================================
// PART 7: THE COMPUTE OPTION
// ============================================

function ItemCount({ control }: { control: Control<FormValues> }) {
  // The compute returns the derived value.
  // The component re-renders only when the count changes.
  const count = useWatch({
    control,
    name: "items",
    compute: (items = []) => items.length,
  });

  return <p>{count} items</p>;
}

// ============================================
// PART 8: THE SUBSCRIPTION TIMING
// ============================================

// โŒ The subscription happens after the value update.
setValue("test", "data");
useWatch({ name: "test" }); // The update is ignored.

// โœ… The subscription happens before the value update.
useWatch({ name: "example" });
setValue("example", "data"); // The update is received.

// ============================================
// PART 9: THE REACT COMPILER
// ============================================

// The watch result is not safe with the React Compiler.
// The compiler may cache the result and render the stale values.
// Use the useWatch for the values that are rendered,
// and the subscribe for the side effects.

// ============================================
// PART 10: THE CHECKLIST
// ============================================

// [ ] The watch is used in the form component that reads the values.
// [ ] The useWatch is used in the child component that reads the values.
// [ ] The control is passed from the useForm to the child.
// [ ] The defaultValue is set for the fallback.
// [ ] The compute is used for the derived values.
// [ ] The subscription timing is checked.

The ten parts covered the watch re-render scope, the useWatch isolated scope, the getValues no subscription, the subscribe side effect, the defaultValue fallback, the exact option, the compute option, the subscription timing, the React Compiler, and the checklist. The through-line is that the two APIs read the same values, and the render boundary is the difference.


Quick Reference

The API comparison

APIRe-rendersUse for
watchThe component that calls useFormThe form-level rendering
useWatchOnly the component that calls the hookThe nested rendering
getValuesNothingThe event handlers
watch callback / subscribeNothingThe side effects

The useWatch options

OptionPurpose
nameThe field or the fields to watch
controlThe form control object
defaultValueThe fallback before the form is mounted
exactThe exact name matching
computeThe derived value subscription
disabledThe subscription disable

The watch overloads

OverloadReturns
watch(name)The single field value
watch(names)The array of field values
watch()The entire form values
watch(callback)The unsubscribe function

The subscription timing

OrderResult
setValue then useWatchThe update is missed
useWatch then setValueThe update is received

Best Practices

โœ… Do This:

// Use the useWatch in the child component
const name = useWatch({ control, name: "name" });                  // โœ…

// Use the compute for the derived values
const count = useWatch({ control, name: "items", compute: (i) => i.length }); // โœ…

// Use the getValues in the event handler
const handleClick = () => getValues();                             // โœ…

โŒ Don’t Do This:

// Use the watch in the render body of a large form
const allValues = watch(); // the whole form re-renders               // โŒ

// Use the useWatch after the setValue
setValue("test", "data"); useWatch({ name: "test" });              // โŒ

Common Pitfalls

PitfallWhy It HappensFix
The whole form re-renders on every keystrokeThe watch is used in the form componentUse the useWatch in the child
The useWatch returns undefined on the first renderThe field is not registeredSet the defaultValue or the defaultValues
The useWatch does not receive the updateThe subscription happens after the setValueSubscribe before the update, or merge with the getValues
The re-render is too frequentThe watched value changes on every keystrokeUse the compute option

Real-World Examples

1. The watch in the form

const coupon = watch("coupon");

2. The useWatch in the child

const coupon = useWatch({ control, name: "coupon" });

3. The getValues in the handler

const handleClick = () => console.log(getValues());

4. The subscribe side effect

watch((values, { type }) => { if (type === "change") autosave(values); });

5. The defaultValue

useWatch({ control, name: "name", defaultValue: "Guest" });

6. The exact option

useWatch({ control, name: "users", exact: true });

7. The compute option

useWatch({ control, name: "items", compute: (i) => i.length });

8. The control prop

<OrderTotal control={control} />

9. The subscription timing

useWatch({ name: "example" }); setValue("example", "data");

10. The custom hook merge

const useFormValues = () => ({ ...useWatch(), ...getValues() });

Visual

The Render Scope

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE RENDER SCOPE                                            โ”‚
โ”‚                                                              โ”‚
โ”‚  watch in the form component                                 โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ The whole form re-  โ”‚  Every keystroke re-renders        โ”‚
โ”‚  โ”‚ renders             โ”‚  the form component                โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  useWatch in the child component                             โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ Only the child re-  โ”‚  The form component does not       โ”‚
โ”‚  โ”‚ renders             โ”‚  re-render                         โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Subscription Timing

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE SUBSCRIPTION TIMING                                     โ”‚
โ”‚                                                              โ”‚
โ”‚  โŒ The subscription after the update:                        โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ setValue("test")    โ”‚  The value is set                  โ”‚
โ”‚  โ”‚ useWatch("test")    โ”‚  The subscription is too late      โ”‚
โ”‚  โ”‚                     โ”‚  The update is ignored             โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  โœ… The subscription before the update:                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ useWatch("example") โ”‚  The subscription is in place      โ”‚
โ”‚  โ”‚ setValue("example") โ”‚  The update is received            โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Compute Option

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE COMPUTE OPTION                                          โ”‚
โ”‚                                                              โ”‚
โ”‚  Without the compute:                                        โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ useWatch("items")   โ”‚  The re-render on every keystroke  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  With the compute:                                           โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ compute: (items) => โ”‚  The re-render only when the       โ”‚
โ”‚  โ”‚   items.length      โ”‚  count changes                     โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
watchThe form-level subscription, re-renders the useForm component
useWatchThe component-level subscription, re-renders the hook component
getValuesThe on-demand read, no subscription
The callback formThe side-effect subscription, no re-render
defaultValueThe fallback before the form is mounted
exactThe exact name matching
computeThe derived value subscription

Key takeaways:

  • The two APIs read the same values, and the render boundary is the difference. The watch re-renders the component that owns the useForm call, and the useWatch re-renders only the component that calls the hook . The extraction of the value-display component is the mechanism that isolates the re-render.
  • The useWatch is the performance choice for the nested rendering. The control prop is the connection between the form and the child, and the child re-renders only when the watched value changes . The form component does not re-render on the keystrokes.
  • The getValues is the no-subscription read. It reads the current values on demand, and it is the mechanism for the event handlers and the effects, not for the render .
  • The callback form is the side-effect subscription. The watch callback runs on every change without a re-render, and the type argument distinguishes the user input from the programmatic change .
  • The compute option reduces the re-render frequency. The function receives the watched value and returns the derived value, and the component re-renders only when the derived value changes .
  • The subscription timing matters. The useWatch subscribes when the component mounts, and a value set before the subscription is ignored. The custom hook that merges the useWatch with the getValues is the workaround .

Remember: The React Hook Form has two ways to read the values during the render, and the choice is the render scope. The watch is the form-level subscription, and the useWatch is the component-level subscription. The getValues is the no-subscription read, and the callback is the side-effect subscription. The compute is the derived-value subscription, and the exact is the name-matching option. The values are the same; the re-render boundary is the difference.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!