skip to Main Content

I am using below package for my demo application.
https://www.npmjs.com/package/mui-react-hook-form-plus

Above package have dependency of react-hook-form

Object key are removed after button click don’t know why ?

I am setting the value like this on button click.

const update = () => {
    const data = {
      person: { firstName: "", lastName: "", sex: "Male" },
    };

    setValues(data);
  };

here is my component

export default function App() {
  const defaultValues = {
    person: { firstName: "", lastName: "", sex: "" },
  };

  const methods = useHookForm<any>({
    defaultValues,
  });

  const { registerState, handleSubmit, getValues, setValues } = methods;
  console.log(getValues());
  const onSubmit = (data: any) => {
    console.log(JSON.stringify(getValues(), null, 2));
  };
  const update = () => {
    const data = {
      person: { firstName: "", lastName: "", sex: "Male" },
    };

    setValues(data);
  };
  return (
    <div className="App">
      <HookFormProvider {...methods}>
        <form onSubmit={handleSubmit(onSubmit)}>
          <Stack direction="row" spacing={2}>
            <HookTextField
              {...registerState("person.firstName")}
              textFieldProps={{ label: "First Name" }}
            />
            <HookTextField
              {...registerState("person.lastName")}
              textFieldProps={{ label: "Last Name" }}
            />
          </Stack>
          <button onClick={update}>set value</button>
          <br />
          {JSON.stringify(getValues("person"), null, 2)}
          <br />
        </form>
      </HookFormProvider>
    </div>
  );
}

code
https://stackblitz.com/edit/vitejs-vite-61ya5m?file=src%2Findex.css,src%2FApp.css&terminal=dev

steps to repr

  1. Run application .. see OBJECT Value { "firstName": "", "lastName": "", "sex": "" }
  2. Click Button see Object { "sex": "Male" }
  3. firstName. and lastName key removed from object why ?

enter image description here

i say internally removing field why
https://github.com/adiathasan/mui-react-hook-form-plus/blob/master/src/utils/form-utils.ts

2

Answers


  1. You don’t need to call an update method via onClick.

    it should be a submit button. handleSubmit does all the works for you.

    function App() {
      const defaultValues = {
        person: { firstName: '', lastName: '', sex: '' },
      };
    
      const methods = useHookForm<any>({
        defaultValues,
      });
    
      const { registerState, handleSubmit, getValues, setValues } = methods;
      console.log(getValues());
      const onSubmit = (data: any) => {
        console.log(JSON.stringify(getValues(), null, 2));
      };
      return (
        <>
          <div className="App">
            <HookFormProvider {...methods}>
              <form onSubmit={handleSubmit(onSubmit)}>
                <Stack direction="row" spacing={2}>
                  <HookTextField
                    {...registerState('person.firstName')}
                    textFieldProps={{ label: 'First Name' }}
                  />
                  <HookTextField
                    {...registerState('person.lastName')}
                    textFieldProps={{ label: 'Last Name' }}
                  />
                </Stack>
                <button>set value</button>
                <br />
                {JSON.stringify(getValues('person'), null, 2)}
                <br />
              </form>
            </HookFormProvider>
          </div>
        </>
      );
    }
    
    export default App;
    

    Demo

    Clarify.

     <button>set value</button>
    

    By doing this, it says button’s default behaviour called submit.

    So it will trigger the handleSubmit via onSubmit.

    <form onSubmit={handleSubmit(onSubmit)}>
    

    if you still want to have the update button.

      const update = () => {
        setValues({...getValues(), sex: 'Male'});
      };
    
    Login or Signup to reply.
  2. The button is missing the type attribute so it has type="submit" by default. When you click the button you are calling update and submitting the form at the same time. The update function overwrites the form state and doesn’t include the fields with falsey values it seems.

    Simply omit the onClick={update} handler from the submit button. I recommend also being explicit about the button type.

    If you have the need for an additional button that does not submit or update the form, i.e. it just needs to access the current form field values, then use the getValues utility.

    const defaultValues = {
      person: { firstName: '', lastName: '', sex: '' },
    };
    
    function App() {
      const methods = useHookForm<any>({
        defaultValues,
      });
    
      const { registerState, handleSubmit, getValues, setValues } = methods;
    
      const onSubmit = (data: any) => {
        // Data is the current updated form field values
    
        console.log("submit", data);
      };
    
      const handleEvent = () => {
        const data = getValues(); // <-- access current values
    
        console.log({ data });
      };
    
      return (
        <div className="App">
          <HookFormProvider {...methods}>
            <form onSubmit={handleSubmit(onSubmit)}>
              <Stack direction="row" spacing={2}>
                <HookTextField
                  {...registerState('person.firstName')}
                  textFieldProps={{ label: 'First Name' }}
                />
                <HookTextField
                  {...registerState('person.lastName')}
                  textFieldProps={{ label: 'Last Name' }}
                />
              </Stack>
              <button type="submit"> // <-- submit type button
                set value
              </button>
              <button
                type="button" // <-- non-submit button
                onClick={handleEvent}
              >
                Event
              </button>
              <br />
              {JSON.stringify(getValues('person'), null, 2)}
              <br />
            </form>
          </HookFormProvider>
        </div>
      );
    }
    

    If you are trying to manually update the form state then it seems you can include the person key in the setValues utility.

    Source Code

    Example:

    setValues(data, ["person"]);
    

    The utility doesn’t do a deep merge, so you can either manually shallow copy all the form field state you want to update, or you can flatten your form state.

    Example:

    const defaultValues = {
      firstName: '', lastName: '', sex: '',
    };
    
    function App() {
      const methods = useHookForm<any>({
        defaultValues,
      });
    
      const { registerState, handleSubmit, getValues, setValues } = methods;
      console.log(getValues());
      const onSubmit = (data: any) => {
        console.log('submit', JSON.stringify(getValues(), null, 2), data);
      };
    
      const update = () => {
        const data = {
           firstName: "", lastName: "", sex: "Male",
        };
    
        setValues(data); // <-- includes all root keys
      };
    
      return (
        <>
          <div className="App">
            <HookFormProvider {...methods}>
              <form onSubmit={handleSubmit(onSubmit)}>
                <Stack direction="row" spacing={2}>
                  <HookTextField
                    {...registerState('firstName')}
                    textFieldProps={{ label: 'First Name' }}
                  />
                  <HookTextField
                    {...registerState('lastName')}
                    textFieldProps={{ label: 'Last Name' }}
                  />
                </Stack>
                <button
                  type="submit"
                  onClick={update}
                >
                  Submit
                </button>
                <br />
                {JSON.stringify(getValues(), null, 2)}
                <br />
              </form>
            </HookFormProvider>
          </div>
        </>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search