Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useFormPersist causes the component to rerender on every field change #33

Open
adams-family opened this issue Feb 9, 2023 · 3 comments

Comments

@adams-family
Copy link

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.

@kamenskiyyyy
Copy link

Me too

@hrasekj
Copy link

hrasekj commented Nov 28, 2023

Yes, watch can be used with callback.

  React.useEffect(() => {
    const subscription = watch((value, { name, type }) =>
      console.log(value, name, type)
    )
    return () => subscription.unsubscribe()
  }, [watch])

https://react-hook-form.com/docs/useform/watch

@nickzelei
Copy link

nickzelei commented May 2, 2024

Okay so I've run into this and was able to work through it by doing two things:

  1. I had change the internals of useFormPersist to use the newer useWatch hook that react-hook-form provides. This causes the interface of useFormPersist to change because now instead of passing in watch, you pass in control.
  2. 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants