ui
ui copied to clipboard
perf(form): scoped field subscription state
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 is attempting to deploy a commit to the shadcn-pro Team on Vercel.
A member of the Team first needs to authorize it.
@shadcn
nice
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?
@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.
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.
- Open the dev tools console
- Type 1 character at a time in each input, you can see its respective label renders once (as expected)
- 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?
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 is right. You can change to onBlur or onSubmit and both work fine. Wish this was the default instead of OnChange.
@UltimateGG same problem. I have fixed it in this way:
- Remove
useFormContext
fromuseFormField
hook - Get form state from
useFormState
like: