Piplup
@piplup/rhf-adaptersmui-materialHooks

useMuiInputAdapterProps

Returns adapter props for building custom MUI Input fields with React Hook Form, taking required and disabled from a surrounding FormControl.

useMuiInputAdapterProps connects a field to React Hook Form and returns props you spread onto MUI's standard (underlined) Input. It's what MuiInputElement uses internally.

Use it when you assemble a field from FormControl, InputLabel, Input and FormHelperText instead of using TextField, for example to put a checkbox or other content between the parts, or to let a parent FormControl decide whether the input is required or disabled.

Import

import { useMuiInputAdapterProps } from "@piplup/rhf-adapters/mui-material";

Usage

The EmailInput below doesn't set required or disabled. It takes both from the FormControl around it. Turn the checkbox off and the field is disabled and left out of the submitted values. Turn it on and submit empty, or type an address without a domain, to see the messages.

"use client";import { useState } from "react";import Stack from "@mui/material/Stack";import FormControl from "@mui/material/FormControl";import FormControlLabel from "@mui/material/FormControlLabel";import FormHelperText from "@mui/material/FormHelperText";import Input from "@mui/material/Input";import InputLabel from "@mui/material/InputLabel";import Checkbox from "@mui/material/Checkbox";import {  MuiButtonElement,  useMuiInputAdapterProps,} from "@piplup/rhf-adapters/mui-material";import { type Control, useForm } from "react-hook-form";type FormValues = { email: string };// The field does not set `required` or `disabled` itself. It picks both up// from the surrounding FormControl, and type="email" adds an email check.function EmailInput({ control }: { control: Control<FormValues> }) {  const { ref, helperText, ...adapter } = useMuiInputAdapterProps({    control,    name: "email",    type: "email",    composeHelperText: true,    messages: { required: "We need an email to send the receipt" },  });  // FormControl does not know about the field error, so pass it to the  // label and helper text directly.  return (    <>      <InputLabel error={adapter.error}>Email</InputLabel>      <Input {...adapter} inputRef={ref} />      <FormHelperText error={adapter.error}>{helperText}</FormHelperText>    </>  );}export default function Page() {  const [sendReceipt, setSendReceipt] = useState(true);  const { control, handleSubmit } = useForm<FormValues>({    defaultValues: { email: "" },  });  return (    <form      noValidate      onSubmit={handleSubmit((values) =>        alert(JSON.stringify(values, null, 2)),      )}    >      <Stack direction="column" spacing={2}>        <FormControlLabel          control={            <Checkbox              checked={sendReceipt}              onChange={(event) => setSendReceipt(event.target.checked)}            />          }          label="Email me a receipt"        />        <FormControl          variant="standard"          required={sendReceipt}          disabled={!sendReceipt}        >          <EmailInput control={control} />        </FormControl>        <div>          <MuiButtonElement control={control} variant="contained" type="submit">            Pay          </MuiButtonElement>        </div>      </Stack>    </form>  );}

How it works

Value handling, type: "number", transforms, and the validation rules with their default messages are the same as in useMuiInputBaseAdapter. The demo relies on one of them: type: "email" adds an email pattern and the message "Please enter an email address."

FormControl fallback. When the hook runs inside a MUI FormControl, it reads that control's state:

  • If you don't pass required, the control's required is used. It becomes a real validation rule, not just an asterisk.
  • If you don't pass disabled, the control's disabled is used. The field is then disabled in React Hook Form too, so it skips validation and is left out of the submitted values.

A value you pass to the hook always wins, including false.

The hook reads the control through React context, so it must run in a component rendered inside the FormControl, as EmailInput is in the demo. If the same component renders both the FormControl and the input, the hook can't see it.

Errors. FormControl doesn't know about the field's validation error. Its InputLabel and FormHelperText stay in their normal colors unless you pass error to them, as the demo does, or use useMuiInputLabelAdapter and useMuiFormHelperTextAdapter, which read the error by field name.

Ref. Input puts ref on its root <div>. Pass the returned ref to inputRef so React Hook Form can focus the input when validation fails. Also remove helperText from the result before spreading, because Input has no such prop.

useMuiFilledInputAdapter and useMuiOutlinedInputAdapter behave the same way for the other two variants.

Props

Prop

Type

Return value

Prop

Type

On this page