Simple Form Handling with react-hook-form

Hi everyone, I am going to explain how you can handle form data using react-hook-form.

I will cover integration of some material-ui elements which are:

  • TextField
  • Checkbox
  • Radio Buttons
  • Select
  • Slider

These are the elements I use most often when working with forms.

These are the steps which I follow to handle form data hassle free.

  1. import

    import { useForm, Controller } from 'react-hook-form'
    
  2. Initialize default values for your form

    const { register, handleSubmit, watch, controller } = useForm({
     defaultValues: {
       firstName: '',
       lastName: '',
       gender: 'female',
       country: 'India',
       languagesKnown: [],
       currentlyWorking: true,
       perHourRate: 50
     }
    })
    

    I always provide default values to the form, if not provided you will receive an error saying 'A component is changing an uncontrolled input to be controlled '.

  3. Initialize the watchFields variable so that you can get updates when the state of each element is changed and run some other logic based on state change.

    const watchFields = watch()
    
  4. Register your elements

    <TextField
    fullWidth
    type='text'
    label='First Name'
    {...register('firstName')} />
    

Full code for the form.
Github Link .

import { Container, Grid, TextField, Button, FormLabel, Checkbox, FormControl, FormGroup, FormControlLabel, RadioGroup, Radio, Select, MenuItem, Switch, Slider } from '@mui/material'
import { useForm, Controller } from 'react-hook-form'

export default function Home() {

  const programmingLanguages = [
    { id: 1, name: 'Javascript' },
    { id: 2, name: 'Java' },
    { id: 3, name: 'Python' }
  ]

  const countries = [
    { id: 1, name: 'India' },
    { id: 2, name: 'USA' },
    { id: 3, name: 'Canada' }
  ]

  const { register, handleSubmit, watch, control } = useForm({
    defaultValues: {
      firstName: '',
      lastName: '',
      gender: 'female',
      country: 'India',
      languagesKnown: [],
      currentlyWorking: true,
      perHourRate: 50
    }
  })

  const watchFields = watch()

  const submit = (data) => {
    console.log({ data })
  }

  return (
    <Container>
      <form onSubmit={handleSubmit(submit)}>
        <Grid container spacing={2} sx={{ marginTop: '10px' }}>
          <Grid item xs={6}>
            <TextField
              fullWidth
              type='text'
              label='First Name'
              {...register('firstName')}
            />
          </Grid>
          <Grid item xs={6}>
            <TextField
              fullWidth
              type='text'
              label='Last Name'
              {...register('lastName')}
            />
          </Grid>
          <Grid item xs={6}>
            <FormLabel>Programming languages known</FormLabel>
            <br />
            {
              programmingLanguages.map(language => <FormControlLabel key={language.id}
                control={<Checkbox
                  value={language.name}
                  {...register('languagesKnown')} />}
                label={language.name} />)
            }
          </Grid>
        </Grid>
        <Grid item xs={6}>
          <FormControl component="fieldset">
            <FormLabel component="legend">Gender</FormLabel>
            <Controller
              control={control}
              name='gender'
              render={({ field }) => <RadioGroup
                {...field}
              >
                <FormControlLabel value="female" key='1' control={<Radio />} label="Female" />
                <FormControlLabel value="male" key='2' control={<Radio />} label="Male" />
                <FormControlLabel value="other" key='3' control={<Radio />} label="Other" />
              </RadioGroup>}
            />
          </FormControl>
        </Grid>
        <Grid item xs={6}>
          <FormLabel>Please select your country</FormLabel>
          <Controller
            name='country'
            control={control}
            render={({ field }) => <Select
              fullWidth
              defaultValue='India'
              {...field}
            >
              {countries.map(country => <MenuItem key={country.id} value={country.name}>{country.name}</MenuItem>)}
            </Select>}
          />
        </Grid>
        <Grid>
          <FormControlLabel control={<Switch defaultChecked {...register('currentlyWorking')} />} label="Currently working" />
        </Grid>
        <Grid item xs={6}>
          <FormLabel>Please select your per hour rate</FormLabel>
          <Controller
            name='perHourRate'
            control={control}
            render={({ field }) => <Slider {...field} aria-label="Default" valueLabelDisplay="auto" />}
          />
          <FormLabel>${watchFields.perHourRate}</FormLabel>
        </Grid>
        <Button type='submit'>Submit</Button>
      </form>
    </Container>
  )
}