useMuiFormLabelAdapter
Returns props for an MUI FormLabel that follows a React Hook Form field's error and disabled state without registering a value.
useMuiFormLabelAdapter returns props for MUI's FormLabel that reflect the state of a field registered elsewhere. It's what MuiFormLabelElement uses internally.
Use the hook when the label is part of a custom field component, so the label, input and helper text all live in one place, as in the example below. For a label placed directly in a form, the element is shorter.
Import
import { useMuiFormLabelAdapter } from "@piplup/rhf-adapters/mui-material";Usage
BioField is built from three hooks: useMuiInputBaseAdapter for the input, this hook for the label, and useMuiFormHelperTextAdapter for the message below. Submit it empty and the label, border and helper text all switch to the error state.
"use client";import { useId } from "react";import Stack from "@mui/material/Stack";import FormLabel from "@mui/material/FormLabel";import FormHelperText from "@mui/material/FormHelperText";import InputBase from "@mui/material/InputBase";import { MuiButtonElement, useMuiFormHelperTextAdapter, useMuiFormLabelAdapter, useMuiInputBaseAdapter,} from "@piplup/rhf-adapters/mui-material";import { type Control, useForm } from "react-hook-form";type FormValues = { bio: string };// A field built from three hooks. Only the input registers the value.// The label and helper text read the same field's error state by name.function BioField({ control }: { control: Control<FormValues> }) { const inputId = useId(); const helperId = `${inputId}-helper`; const { ref, helperText: _inputHelperText, ...input } = useMuiInputBaseAdapter({ control, name: "bio", required: true, maxLength: 160, messages: { required: "Tell us a little about yourself", maxLength: (max) => `Keep it under ${max} characters`, }, }); const { helperText: _labelHelperText, ...label } = useMuiFormLabelAdapter< FormValues, "bio", HTMLLabelElement >({ control, name: "bio", }); const helper = useMuiFormHelperTextAdapter< FormValues, "bio", HTMLParagraphElement >({ control, name: "bio", composeHelperText: true, children: "Shown on your public profile", }); return ( <Stack spacing={0.5}> <FormLabel {...label} htmlFor={inputId} required> Bio </FormLabel> <InputBase {...input} id={inputId} inputRef={ref} multiline minRows={3} slotProps={{ input: { "aria-describedby": helperId } }} sx={{ p: 1, border: 1, borderRadius: 1, borderColor: input.error ? "error.main" : "divider", }} /> <FormHelperText {...helper} id={helperId} /> </Stack> );}export default function Page() { const { control, handleSubmit } = useForm<FormValues>({ defaultValues: { bio: "" }, }); return ( <form noValidate onSubmit={handleSubmit((values) => alert(JSON.stringify(values, null, 2)), )} > <Stack direction="column" spacing={2}> <BioField control={control} /> <div> <MuiButtonElement control={control} variant="contained" type="submit"> Save </MuiButtonElement> </div> </Stack> </form> );}How it works
Read-only. The hook doesn't call useController, so it registers nothing: no value, no rules, no onChange. It subscribes to the form state with useFormState and looks up the field by name. You can render several labels or helper texts for one field, and none of them changes what is submitted. The name must match a field that some input registers.
It needs control, or a surrounding FormProvider/FormContainer.
Returned props. error, disabled, className, style, classes and ref, plus a helperText that FormLabel doesn't accept. Remove it before spreading, as the demo does.
erroristruewhile the field has a validation error, or whatever you pass aserror.disabledistruewhen you passdisabledor the whole form is disabled (useForm({ disabled: true })). If you pass nothing and the label is inside a MUIFormControl, the control'sdisabledis used.
Both are passed to FormLabel explicitly, even when false. That means they override the error and disabled of a surrounding FormControl for this label.
The label doesn't know when the input itself is disabled through its own disabled prop. Pass the same disabled to both hooks, or disable the whole form.
useMuiInputLabelAdapter is the same hook for InputLabel, but it doesn't read FormControl's disabled. The generic reading of field state is described in useFieldStateAdapter.
Props
Prop
Type
Return value
Prop
Type