Piplup
@piplup/rhf-adaptersmui-materialHooks

useMuiIconButtonAdapter

Returns props for an MUI IconButton that submits or resets a React Hook Form form and disables itself from form state.

useMuiIconButtonAdapter returns props you spread onto MUI's IconButton so it can submit or reset a React Hook Form form and disable itself from the form state. It's what MuiIconButtonElement uses internally.

The hook behaves exactly like useMuiButtonAdapter. Icon buttons usually sit inside compact controls such as search bars, toolbars and table rows, so the hook is handy for building those as one component with the form wiring included.

Import

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

Usage

A search bar with two icon buttons. The search button uses disableOnError, so it's disabled while the query is shorter than three characters. The clear button is type="reset" and restores the empty default value.

"use client";import ClearIcon from "@mui/icons-material/Clear";import SearchIcon from "@mui/icons-material/Search";import IconButton from "@mui/material/IconButton";import Stack from "@mui/material/Stack";import {  MuiTextFieldElement,  useMuiIconButtonAdapter,} from "@piplup/rhf-adapters/mui-material";import { type Control, useForm } from "react-hook-form";type FormValues = { query: string };// Disabled while the form is invalid, e.g. when the query is too short.function SearchButton({ control }: { control: Control<FormValues> }) {  // IconButton has no error or helperText props, so keep them off the DOM.  const {    error: _error,    helperText: _helperText,    ...adapter  } = useMuiIconButtonAdapter<FormValues, HTMLButtonElement>({    control,    type: "submit",    disableOnError: true,  });  return (    <IconButton aria-label="Search" color="primary" {...adapter}>      <SearchIcon />    </IconButton>  );}// type="reset" resets the form to its default values.function ClearButton({ control }: { control: Control<FormValues> }) {  const {    error: _error,    helperText: _helperText,    ...adapter  } = useMuiIconButtonAdapter<FormValues, HTMLButtonElement>({    control,    type: "reset",  });  return (    <IconButton aria-label="Clear search" {...adapter}>      <ClearIcon />    </IconButton>  );}export default function Page() {  const { control, handleSubmit } = useForm<FormValues>({    mode: "onChange",    defaultValues: { query: "" },  });  return (    <form      noValidate      onSubmit={handleSubmit((values) =>        alert(JSON.stringify(values, null, 2)),      )}    >      <Stack direction="row" spacing={1} sx={{ alignItems: "flex-start" }}>        <MuiTextFieldElement          control={control}          name="query"          label="Search products"          size="small"          minLength={3}          messages={{ minLength: "Type at least 3 characters" }}        />        <SearchButton control={control} />        <ClearButton control={control} />      </Stack>    </form>  );}

How it works

For the full behavior (form state subscription, the disabling table, reset on type="reset", class names, helper text) see How it works on the button hook page. Points that come up with icon buttons:

disableOnError follows the whole form. The error state is true whenever the form's isValid is false. The demo has one field, so that's the query. The form uses mode: "onChange", so the error message appears as you type and the button re-enables as soon as the query is valid. An empty query is valid here because there's no required rule.

Disabling on one field only. If the form has other fields, isValid covers them too. Pass your own error to base the state on one field instead. It replaces the isValid check:

const { errors } = useFormState({ control, name: "query" });

const adapter = useMuiIconButtonAdapter<FormValues, HTMLButtonElement>({
  control,
  type: "submit",
  disableOnError: true,
  error: !!errors.query,
});

errors only holds a field once it has been validated, so with this approach untouched fields don't disable the button.

Accessible name. The adapter doesn't add a label. An icon has no text, so give each IconButton an aria-label, as the demo does.

IconButton has no error or helperText props. Remove them from the returned object before spreading it, as the demo and the element do.

Props

Prop

Type

Return value

Prop

Type

On this page