Home > Enterprise >  Add effect to any fields changing
Add effect to any fields changing

Time:07-01

I am using React with react-hook-form and I'm trying to store every value user enters in localStorage to persist form state. I know I can redefine onChange handler library provides and add to actual handler storing its value, but I'm looking for solution, that allow to provide custom onChange or onBlur handler that I can provide to useHook and it will trigger on any field changes. Something like this:

const App = () => {
  const methods = useForm({
    onChange: (allValues) => localStorage.setItem('form', allValues),
  }
  /* ... */
}

CodePudding user response:

I am not aware of anything to do this, but you can probably use something like this :

const { watch } = useForm();

const watchField1 = watch("field1");
const watchField2 = watch("field2");
const watchField3 = watch("field3");

useEffect(() => {
  localStorage.setItem('form', {
    field1: watchField1,
    field2: watchField2,
    field3: watchField3,
  });
}, [watchField1, watchField2, watchField3]);

CodePudding user response:

@teehbow's answer got me thinking about watch not only exact field value by its name, but the whole form. Reffering to docs, if you don't pass field name to hook, you will get the object with all form values.

const name = useWatch('first-name') // watch and return only first name as string
const values = useWatch()           // watch all the form fields and returns form values object

If you don't wrap your form with FormProvider, then you also need to pass control to your watch hook. If you do, you can use it as in example above.

As I already have a value that subscribed to form changes, I only need to create effect that depends on values. To prevent unnecessary render of parent form element, i put out storing values to new component that do nothing but it

function PersistWatch(): null {
  const values = useWatch()
  
  useEffect(() => {
    localStorage.setItem('key', values)
  }, [values])
  
  return null
}

and put this component inside FormProvider. And it works! Also it's possible to pass local storage key using props and it will make component reusable in different forms.

  • Related