useFormPersist causes the component to rerender on every field change
adams-family opened this issue · 3 comments
I'm not sure if this is fixable (but I hope it is). After setting up useFormPersist
using the repro steps below, my page where useForm
sits gets rerendered on every field change:
import useFormPersist from 'react-hook-form-persist'
const { setValue, watch } = form;
useFormPersist("form-storage", {
watch,
setValue,
storage: window.localStorage
});
By commenting out the useFormPersist
command above the problem is resolved but obviously the functionality is gone.
Motivation: Measured by Chrome DevTools / Performance tab, there is a 4-fold performance degradation with this command turned on (moving from 100ms to 400-500ms on my test case).
Suggestion: I think that if possible, the form should be persisted without causing the current element to rerender.
Me too
Yes, watch
can be used with callback.
React.useEffect(() => {
const subscription = watch((value, { name, type }) =>
console.log(value, name, type)
)
return () => subscription.unsubscribe()
}, [watch])
Okay so I've run into this and was able to work through it by doing two things:
- I had change the internals of
useFormPersist
to use the neweruseWatch
hook thatreact-hook-form
provides. This causes the interface ofuseFormPersist
to change because now instead of passing inwatch
, you pass incontrol
. - The
useFormPersist
hook must be nested inside of a child component.
These two things fix the rendering issues because it causes that child component to re-render only instead of the main form component.
interface FormPersistProps {
form: UseFormReturn<any>;
formKey: string;
}
function FormPersist(props: FormPersistProps): ReactElement {
const { form, formKey } = props;
useFormPersist(formKey, {
control: form.control,
setValue: form.setValue,
storage: isBrowser() ? window.sessionStorage : undefined,
});
return <></>;
}
Then I just have this nested like so:
function MainForm() {
const form = useForm();
return (
<div>
<FormPersist form={form} formKey={"mykey"} />
<form>...</form>
</div>
);
}
This will not work with this current version of useFormPersist
due to the old watch() method not working the same as the useWatch
hook.
Can read more about it here: https://react-hook-form.com/docs/usewatch
PR where I made these changes if folks are interested: https://github.com/nucleuscloud/neosync/pull/1891/files