7

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?
6
  • Could you provide a working example and the full code (the component definition and imports)? Commented Jul 21, 2020 at 8:59
  • 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 Commented Jul 21, 2020 at 9:14
  • I haven't used react-hook-form yet, but from looking at the API docs you can use the setValue method Commented Jul 21, 2020 at 9:29
  • 1
    there is a codesandbox in the doc which may help: codesandbox.io/s/react-hook-form-v6-controller-qsd8r Commented Jul 21, 2020 at 10:11
  • @Christiaan When I use the setValue I am getting: A component is changing the uncontrolled value state of Autocomplete to be controlled.' Commented Jul 21, 2020 at 10:57

2 Answers 2

12

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'),
    } 
  });
Sign up to request clarification or add additional context in comments.

3 Comments

I don't have the render prop. Can I use 'as' ?
Why not? It is documented here: react-hook-form.com/api/#Controller
onChange={(_, data) => props.onChange(data)} did not work for me. props has field, fieldState, 'formState` as properties and onChange is present inside of field. So change it to onChange={(_, data) => props.field.onChange(data)}, works just fine.
1

Here is the simplest way to do it render your Autocomplete component inside Controller from react hook from, use onChange and value from the render function to control the value

<Controller
control={control}
name="type"
rules={{
  required: 'Veuillez choisir une réponse',
}}
render={({ field: { onChange, value } }) => (
  <Autocomplete
    freeSolo
    options={['field', 'select', 'multiple', 'date']}
    onChange={(event, values) => onChange(values)}
    value={value}
    renderInput={(params) => (
      <TextField
        {...params}
        label="type"
        variant="outlined"
        onChange={onChange}
      />
    )}
  />
)}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.