ui icon indicating copy to clipboard operation
ui copied to clipboard

perf(form): scoped field subscription state

Open MomenSherif opened this issue 10 months ago • 7 comments

Improve react hook form rerenders

using useFormState to scope fieldState subscription at field level to avoid unnecessary rerender for other fields

Before

https://www.loom.com/share/4b5b78b4efe14d7b947c8b5de13da678

After

https://www.loom.com/share/7620fe449325438a8270f68f86ee5111

MomenSherif avatar Aug 25 '23 16:08 MomenSherif

@MomenSherif is attempting to deploy a commit to the shadcn-pro Team on Vercel.

A member of the Team first needs to authorize it.

vercel[bot] avatar Aug 25 '23 16:08 vercel[bot]

@shadcn

MomenSherif avatar Sep 06 '23 09:09 MomenSherif

nice

syssam avatar Apr 24 '24 09:04 syssam

Works and only re-renders the field it needs to, but after submit it seems to revert and starts re-rendering every field each time you type. Anyone else getting this?

UltimateGG avatar May 04 '24 18:05 UltimateGG

@MomenSherif Thanks for this PR. It helped me fix some performance issues and un-necessary renders that have been difficult to isolate. It works great. Without this PR, changes to a single input would cause the parent for component (that calls useForm) to re-render, which caused all of the children (the entire form) to also re-render. This PR removes the extra renders.

@UltimateGG I'm seeing the correct behavior (a reduction in re-renders) after the initial form load and after a submit+reset. Do you have a CodeSandbox example?

@shadcn This would be a great PR to have merged. It's a small change but makes a big impact.

BrendanC23 avatar May 07 '24 16:05 BrendanC23

Here is CSB: https://codesandbox.io/p/devbox/shadcn-ui-vite-forked-84ysks

I applied the same changes as in the PR to form.tsx, added a console.log in the label.tsx so we can see when labels render.

  1. Open the dev tools console
  2. Type 1 character at a time in each input, you can see its respective label renders once (as expected)
  3. Submit the form, and type another character, every label now re-renders each keypress.

Possibly a bug with the underlying hookform package subscription, or maybe how I setup the form submission?

UltimateGG avatar May 08 '24 03:05 UltimateGG

That has to do with the reValidateMode, which is onChange by default. See these docs. If you change it to reValidateMode: "onSubmit", then after clicking submit, only the label associated with the edited input will re-render. See this CSB.

BrendanC23 avatar May 08 '24 13:05 BrendanC23