5
votes

I am having issues with React Hook Forms with Material UI Components and I can't really find resources on this. I have a page where I fetch the countries and the current profile information and I want to show it inside the form. Initially I want to set the country to Germany.

const [countries, setCountries] = useState([]);
const { control, handleSubmit, register, reset } = useForm();
const [currentProfile, setCurrentProfile] = useState<profiles.resProfileFields>();

useEffect(() => {
  const getProfileData = async () => {
    try {
      const profile = await api.get(profiles.getById, { id: profileId });
      if (profile != null && profile != undefined) {
        setCurrentProfile(profile);
        setcountryId(profile.country.id);
      }

    } catch (err) {
      console.log(`error getting: ${err}`);
    }
  };
  getProfileData();
  getCountries();
}, [profileId]);


useEffect(() => {
  reset(currentProfile);
}, [currentProfile]);

const getCountries = () => {
  api
    .get(routes.countries.list, {})
    .then(res => {
      setCountries(res);
    })
    .catch(err => { });
};

<form onSubmit={handleSubmit(onSubmit)}>


  <TextField
    inputRef={register}
    name="name"
    label="* Name"
    InputLabelProps={{
      shrink: true
    }}
    variant="outlined"
    placeholder="Name"
    className="form-item-full"
  />

  <Controller
    name="country"
    as={
      <Autocomplete
        className="form-item"
        options={countries}
        getOptionLabel={option => option.name}
        renderInput={params => (
          <TextField
            {...params}
            inputRef={register}
            label="Country"
            placeholder="Select a Country"
            InputLabelProps={{
              shrink: true
            }}
            variant="outlined"
          />
        )}
      />
    }
    defaultValue="Germany"
    control={control}
  />
</form>
  1. How can I initially set/reset the value to Germany?
  2. How can I post the Id of the country when I submit?
1
Could you provide a working example and the full code (the component definition and imports)? - Chris
It's a very big project. I can't make Material UI Autofill to work with React hook forms. Is there any examples I can check? I want to set an initial value that I get from an API call then I want to submit and update the form - Missak Boyajian
I haven't used react-hook-form yet, but from looking at the API docs you can use the setValue method - Chris
there is a codesandbox in the doc which may help: codesandbox.io/s/react-hook-form-v6-controller-qsd8r - Bill
@Christiaan When I use the setValue I am getting: A component is changing the uncontrolled value state of Autocomplete to be controlled.' - Missak Boyajian

1 Answers

8
votes

In the codesandbox suggested by Bill you can see an exact example.

The Controller with the Autocomplete component should look like this:

    <Controller
      render={props => (
        <Autocomplete
          {...props}
          options={countries}
          getOptionLabel={option => option.name}
          renderInput={params => (
            <TextField
              {...params}
              label="Country"
              placeholder="Select a Country"
              InputLabelProps={{
                shrink: true
              }}
              variant="outlined"
            />
          )}
          onChange={(_, data) => props.onChange(data)}
        />
      )}
      name="country"
      control={control}
    />

Because the selected country actually is an Object, you will have to set the German country object in the defaultValues:

const { control, handleSubmit, register, reset } = useForm({ 
  defaultValues: {
    country: { name: 'Germany', id: 1234 },
  } 
});

If you don't want to 'hardcode' the country in the defaultValues Object, you could move the getCountries call up one level and pass it to the form. You can now conditionally render the form when all data is available and find the country in the countries list like so:

const MyForm = ({ countries }) => {
  const { control, handleSubmit, register, reset } = useForm({ 
    defaultValues: {
      country: countries.find(({ name }) => name === 'Germany'),
    } 
  });