Skip to content

useWatch computed value performance #12501

@JRebella

Description

@JRebella

Is your feature request related to a problem? Please describe.
Relevant when dealing with big forms and conditional fields

Describe the solution you'd like

The scenario:

Imagine you have a form with an input that fires many change events, like a simple text input (call it userName). And then you have another input that you conditionally render or change depending on the value of your first text input. Imagine the condition here is, when userName is of length > 10, also render nickname field

The way of solving this would be to use useWatch to watch the value of useName. Calculate if usernName.length > 10, then if true render nickname:

const MyFormFields = () => {
  const { register } = useFormContext();

  const userNameValue = useWatch({ name: 'userName' });

  const displayNicknameField = userNameValue.length > 10;

  return (
    <>
      <input {...register('userName')} />

      {displayNicknameField && <input {...register('nickname')} />}
    </>
  );
};

The problem:

Every keystroke on userName will cause a re-render. But in reality in most cases we wouldn't need to, we really only care of displayNicknameField changing

The proposal:

Would it be possible to have useWatch accept a callback to compute a value (quite similar to useMemo) but only cause a re-render when said computed value changes?

Combining this

const userNameValue = useWatch({ name: 'userName' });
const displayNicknameField = userNameValue.length > 10;

Into this

const displayNicknameField = useWatch({ name: 'userName', compute: currentValue => currentValue.length > 10 });

For the first 9 keystrokes of userName, displayNicknameField would just be false, resulting in no re-renders. Only at the 10th when it actually changes to true, it would cause its first re-render

Describe alternatives you've considered
Same low-re-render behavior can probably be achieved by combining watch with a callback subscription and a setState, but it would be great if this was built in within watch into a simply one-liner

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestrequest a feature to be addedwaiting-up-voteWaiting for votes from the community.

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions