Published on

How to Use Material-UI DatePicker with react-hook-form

Authors
  • Name
    Ripal & Zalak
    Twitter

How to Use Material-UI DatePicker with react-hook-form

Integrating Material-UI (MUI) DatePicker with react-hook-form can be tricky, especially when dealing with controlled vs uncontrolled components. In this guide, we'll explore the best practices to correctly handle date values while ensuring proper form validation.

Why Use react-hook-form with MUI DatePicker?

  • Performance-friendly: react-hook-form reduces unnecessary re-renders.
  • Simplifies validation: Easy integration with Yup or custom validation rules.
  • Supports controlled components: Ensures MUI DatePicker works seamlessly with form state.

Common Issues and Fixes

Before we dive into solutions, let’s examine common issues developers face:

❌ Issue 1: Controller not updating the form value

If you use MUI DatePicker inside a Controller but don’t properly pass field.onChange, your form won’t register changes.

❌ Issue 2: register() doesn’t work with DatePicker

Using register() directly with DatePicker leads to issues since DatePicker doesn’t emit an event like typical inputs.

✅ Solution: Use Controller to manage DatePicker

Implementing MUI DatePicker with react-hook-form

1️⃣ Basic Setup

Ensure you have the necessary dependencies:

npm install @mui/lab @mui/material @mui/x-date-pickers date-fns react-hook-form

2️⃣ Controlled Component with Controller

import React from 'react'
import { useForm, Controller } from 'react-hook-form'
import { LocalizationProvider, DatePicker } from '@mui/x-date-pickers'
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'
import { TextField, Button } from '@mui/material'

export default function DatePickerForm() {
  const { control, handleSubmit } = useForm()

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

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <LocalizationProvider dateAdapter={AdapterDateFns}>
        <Controller
          name="date"
          control={control}
          defaultValue={null}
          render={({ field: { onChange, value }, fieldState: { error } }) => (
            <DatePicker
              label="Select Date"
              value={value}
              onChange={onChange}
              renderInput={(params) => (
                <TextField {...params} error={!!error} helperText={error?.message} />
              )}
            />
          )}
        />
      </LocalizationProvider>
      <Button type="submit" variant="contained">
        Submit
      </Button>
    </form>
  )
}

3️⃣ Handling Validations

You can easily add validation rules using rules in Controller:

<Controller
  name="date"
  control={control}
  rules={{ required: 'Date is required' }}
  render={({ field, fieldState: { error } }) => (
    <DatePicker
      label="Select Date"
      value={field.value}
      onChange={field.onChange}
      renderInput={(params) => (
        <TextField {...params} error={!!error} helperText={error?.message} />
      )}
    />
  )}
/>

4️⃣ Handling Default Values and State Updates

If you want to set a default date:

const { control } = useForm({
  defaultValues: { date: new Date() },
})

This ensures that DatePicker is initialized with a value and avoids uncontrolled component warnings.

FAQ

1️⃣ Why is my DatePicker value null on form submit?

Ensure you are using Controller and passing onChange correctly inside the render method.

2️⃣ Can I use register() instead of Controller?

No, register() works for basic inputs, but DatePicker requires Controller since it doesn’t emit native change events.

3️⃣ How can I use react-hook-form validation with DatePicker?

Use the rules prop inside Controller to enforce validation rules like required fields.