Piplup
@piplup/rhf-adaptersmui-x-date-pickersHooks

useMuiXStaticDateTimePickerAdapter

Returns adapter props for MUI X StaticDateTimePicker with React Hook Form. The picker has no text field, so you render the error message yourself.

useMuiXStaticDateTimePickerAdapter returns React Hook Form props for MUI X's StaticDateTimePicker, the always-visible date-time picker. It's what MuiXStaticDateTimePickerElement uses internally.

The element shows no validation message at all. Use the hook when the user needs to see why a value was rejected: you get the error state and message back and decide where to render them.

Import

import { useMuiXStaticDateTimePickerAdapter } from "@piplup/rhf-adapters/mui-x-date-pickers";

Usage

This PublishAtField schedules a post on the hour or half hour, up to two weeks ahead. Pick tomorrow, leave the time as it is, and submit to see the message rendered under the picker.

Select date & time
:
October 2026
SMTWTFS
"use client";import dayjs, { type Dayjs } from "dayjs";import FormHelperText from "@mui/material/FormHelperText";import Stack from "@mui/material/Stack";import { LocalizationProvider, StaticDateTimePicker } from "@mui/x-date-pickers";import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";import { MuiButtonElement } from "@piplup/rhf-adapters/mui-material";import { useMuiXStaticDateTimePickerAdapter } from "@piplup/rhf-adapters/mui-x-date-pickers";import { type Control, useForm } from "react-hook-form";type FormValues = { publishAt: Dayjs | null };// Posts go out on the hour or half hour, from now up to two weeks ahead.function PublishAtField({ control }: { control: Control<FormValues> }) {  const { error, helperText, required: _required, ...adapter } = useMuiXStaticDateTimePickerAdapter<    Dayjs,    FormValues,    "publishAt",    HTMLDivElement  >({    control,    name: "publishAt",    required: true,    composeHelperText: true,    disablePast: true,    minDate: dayjs(),    maxDate: dayjs().add(14, "day"),    shouldDisableTime: (value, view) => view === "minutes" && value.minute() % 30 !== 0,    messages: {      required: "Pick when to publish",      disablePast: "Choose a time later than now",      maxDate: "You can schedule up to two weeks ahead",      "shouldDisableTime-minutes": "Posts go out at :00 or :30",    },  });  return (    <div>      <StaticDateTimePicker        ampm={false}        slotProps={{ actionBar: { actions: [] } }}        {...adapter}      />      {error && <FormHelperText error>{helperText}</FormHelperText>}    </div>  );}export default function Page() {  const { control, handleSubmit } = useForm<FormValues>({    defaultValues: { publishAt: null },  });  return (    <LocalizationProvider dateAdapter={AdapterDayjs}>      <form        noValidate        onSubmit={handleSubmit((values) =>          alert(`Scheduled for ${values.publishAt?.format("ddd D MMM, HH:mm")}`),        )}      >        <Stack direction="column" spacing={2}>          <PublishAtField control={control} />          <div>            <MuiButtonElement control={control} variant="contained" type="submit">              Schedule post            </MuiButtonElement>          </div>        </Stack>      </form>    </LocalizationProvider>  );}

How it works

Validation is the same as in useMuiXDateTimePickerAdapter: date checks first, then minTime, maxTime, shouldDisableTime and minutesStep, with the same keys and default messages. What changes is the wiring, because a static picker has no text field and no popup.

No slotProps.textField. Unlike the DateTimePicker hook, this one does not take slotProps and does not build a text field slot. It returns error, helperText and required as plain values. StaticDateTimePicker has no props for them, so take them off the result before spreading and render them yourself, as the example does with FormHelperText. With composeHelperText: true, helperText holds the error message.

No touched state. The hook ignores any onBlur you pass and has no onClose to wrap. The returned onBlur is React Hook Form's, but StaticDateTimePicker never calls it. The field is never marked as touched, so mode: "onBlur" and mode: "onTouched" do not validate it before the first submit. Use the default onSubmit mode or onChange.

Every pick changes the value. The form value updates on each selection in the picker, not when the user presses an action button. Picking a day with no value yet keeps the current time of day, so in the example it usually fails the :00/:30 rule until a minute is chosen. The example hides the action bar with slotProps={{ actionBar: { actions: [] } }} for that reason.

Ref. React Hook Form's ref and your ref are merged and attached to the picker's root element. There is no input to focus, so setFocus and shouldFocusError do nothing for this field.

Props

Prop

Type

Return value

Prop

Type

On this page