MUI + React Hook Formでフォーム作成

2024/01/03に公開

はじめに

今回作るMUI + React Hook Formのソースコードは↓こちらです。
https://github.com/49takaya3989/sample_react_mui_react-hook-form

開発環境

パッケージマネージャー:pnpm
バンドラー:Vite
react: 18.2.0
typescript: 5.2.2
react-hook-form: 7.49.2
@mui/material: 5.15.0
@mui/x-date-pickers: 6.18.6

MUIとは?

マテリアル UI は、Google のマテリアル デザインを実装する React UI コンポーネントのライブラリです。

https://mui.com/material-ui/getting-started/

React Hook Formとは?

React Hook Form の設計と哲学は、ユーザーと開発者のエクスペリエンスに重点を置いています。このライブラリは、パフォーマンスを微調整し、アクセシビリティを向上させることで、よりスムーズな対話エクスペリエンスをユーザーに提供することを目的としています。パフォーマンスの強化には次のようなものがあります。

https://react-hook-form.com/get-started#Designandphilosophy

Reactの環境構築について

今回、Reactの環境構築に関する説明は省きますが、下記添付記事でVite+React+TypeScriptの環境構築方法を解説しているので、よければ参照ください。
https://zenn.dev/takaya39/articles/207e3e393081d9

MUIとReact Hook Formでフォーム作成

MUIとReact Hook Formでフォームを作成する際、制御コンポーネントと非制御コンポーネントに関しての話が絡んできます。非制御・制御コンポーネントに関するざっくりとしたイメージ↓
https://twitter.com/49takaya3989/status/1736247549139505451

必要なパッケージのインストール

pnpm add @mui/material @mui/x-date-pickers @emotion/react @emotion/styled react-hook-form dayjs

※styled-componentsを使用する際は、別のパッケージが必要です。詳しくは公式を参照してください。

MUIでフォーム作成

MUIで適当にフォームを作成する。

function App() {
・・・中略・・・
  return (
    <Container maxWidth="sm" sx={{ pt: 5 }}>
      <Box component="form" onSubmit={handleSubmit} sx={{ mt: 1 }}>
        <Stack spacing={3}>
          <TextField id="text" label="テキスト" />
          <FormControl>
            <InputLabel id="select">セレクトボックス</InputLabel>
            <Select labelId="select" id="select" label="セレクトボックス" defaultValue="0" >
              <MenuItem value={"0"}>0</MenuItem>
              <MenuItem value={"1"}>1</MenuItem>
              <MenuItem value={"2"}>2</MenuItem>
              <MenuItem value={"3"}>3</MenuItem>
            </Select>
          </FormControl>
          <FormGroup>
            <FormLabel id="checkbox">チェックボックス</FormLabel>
            <FormControlLabel control={<Checkbox />} label="" />
            <FormControlLabel control={<Checkbox />} label="" />
            <FormControlLabel control={<Checkbox />} label="" />
          </FormGroup>
          <FormControl>
            <FormLabel id="radio">ラジオ</FormLabel>
            <RadioGroup aria-labelledby="radio" name="radio">
              <FormControlLabel value="radio1" control={<Radio />} label="radio1" />
              <FormControlLabel value="radio2" control={<Radio />} label="radio2" />
              <FormControlLabel value="radio3" control={<Radio />} label="radio3" />
            </RadioGroup>
          </FormControl>
	  <LocalizationProvider dateAdapter={AdapterDayjs}>
            <DatePicker label="date" format="YYYY/MM/DD" />
          </LocalizationProvider>
          <Button type="submit" color="primary" variant="contained" size="large">
            ボタン
          </Button>
        </Stack>
      </Box>
    </Container>
  )
}
export default App

React Hook FormをMUIに繋げる

MUIの<TextField />などは制御コンポーネントと非制御コンポーネントどちらとしても扱うことができる。
非制御コンポーネント:defaultValueを使用
制御コンポーネント:<Controller />とvalueやonChangeなどを使用

<DatePicker />は非制御コンポーネントとして扱えない。

非制御コンポーネントとして扱う場合

繋げるだけであれば下記コードでできる。

const { register, handleSubmit } = useForm()
・・・中略・・・
return (
  <Box component="form" onSubmit={handleSubmit(onSubmit)}>
    <TextField {...register("text")} />
    <Button type="submit">ボタン</Button>
  </Box>
)

これをMUIでフォーム作成で作成したフォームに落とし込むと
https://github.com/49takaya3989/sample_react_mui_react-hook-form/blob/main/src/MUI%2BRHF_with_register/index.tsx
<DatePicker />だけはregisterで繋ぎ込みができないので省略

制御コンポーネントとして扱う場合

https://github.com/49takaya3989/sample_react_mui_react-hook-form/blob/main/src/MUI%2BRHF_with_controller/index.tsx

以上!!

参考記事

https://zenn.dev/buyselltech/articles/51da30508f9687#制御コンポーネントと非制御コンポーネント
https://dev.classmethod.jp/articles/mui-v5-rhf-v7/

Discussion