React-Hook-Formの使い方（Part3：MUIのバリデーション）🌟

## はじめに
Part1ではRHFの使い方。Part2ではRHFとyupを合わせて利用する方法を見ていきました。のPart3ではMUIとの併用を見ていきます。

## パッケージインストール
今回インストールするものはありません。
MUIのバリデーションは今までのやり方にひと手間加えるだけなので簡単です！

## MUIとRHFの使い方
### 方法
MUIはregisterを使った登録はできません。ControllerコンポーネントをimportしてControllerコンポーネントのpropsにMUIを渡すことでバリデーションやvalueの取得を行います。

### Controllerコンポーネントのimport
react-hook-formからControllerをimportします。

```ts
import { useForm, SubmitHandler, Controller } from "react-hook-form";
```

### Controllerコンポーネントの定義
Controllerを定義します。propsには「name」・「control」・「render」を定義します。それぞれのpropsを説明します。

* name  
nameはregisterと同様の意味を持ちます。name属性を登録してRHFから制御できるようにします。よって、nameのpropsには"email"やpassword"などの自由な値を渡すことが出来ます。

* control
controlのPropsにはcontrolを渡します。controlはuseFormから取得できます。

```ts
  const {control} = useForm();
```

* render
renderには関数を指定します。指定した関数はfieldを受け取ります。fieldにはcontrolで指定したpropsの値が入っています。また、指定した関数はMUIを返します。
以下の例では戻り値のMUIとしてTextFieldを返しています。また、TextFieldのpropsにはfieldをスプレッドして指定します。こうすることで、MUIのvalue値をRHFで取得できるようになります。

```ts
 render={({ field }) => (
          <TextField
            {...field}
          />
        )}
```

以上の定義をまとめたコードが以下になります。これで、RHFからMUIのvalue値を取得できます。

```ts
<Controller
        name="email"
        control={control}
        render={({ field }) => (
          <TextField
            {...field}
          />
        )}
      />
```

### エラーメッセージの出力
あとはエラーメッセージを出せるようにします。part2の知識があればココを読まなくても書けそうですね。
以下の例のコードではemailの入力を受け付けるMUIとして定義しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669821/d3659ef6-f279-363e-3ed2-52864a89ef13.png)
※テキストフィールドの右の3点リーダーと丸のやつはNortonが勝手に表示しているやつです。

```ts
<Controller
        name="email"
        control={control}
        defaultValue="example@gmail.com"
        render={({ field }) => (
          <TextField
            {...field}
            type="email"
            label="Email"
            variant="outlined"
            error={!!errors.email}
            helperText={errors.email ? errors.email?.message : ""}
          />
        )}
      />
```

## 注意点
defaultのvalueを指定しないとエラーが出てしまいます。defaultValue=""などを指定することで回避できます。

## 全体のコード
```ts
import { Button, TextField } from "@mui/material";
import { useForm, SubmitHandler, Controller } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

// submitされる値の型定義
type IFormInputs = {
  email: String;
  password: string;
};

// submitをハンドリング
const formSubmitHandler: SubmitHandler<IFormInputs> = (data) => {
  console.log(data);
};

// スキーマ
const schema = yup.object().shape({
  email: yup
    .string()
    .email("メールの書式に従ってください")
    .required("emailは必須です"),
  password: yup
    .string()
    .min(4, "4桁以上必須")
    .max(20, "最大20桁")
    .required("必須です")
});

export default function App() {
  // useForm
  const {
    register,
    handleSubmit,
    watch,
    control,
    formState: { errors }
  } = useForm({
    resolver: yupResolver(schema)
  });

  // JSX
  return (
    <form onSubmit={handleSubmit(formSubmitHandler)}>
      <Controller
        name="email"
        control={control}
        defaultValue="example@gmail.com"
        render={({ field }) => (
          <TextField
            {...field}
            type="email"
            label="Email"
            variant="outlined"
            error={!!errors.email}
            helperText={errors.email ? errors.email?.message : ""}
          />
        )}
      />
      <br />
      <br />
      <Controller
        name="password"
        control={control}
        render={({ field }) => (
          <TextField
            {...field}
            type="password"
            label="Password"
            variant="outlined"
            error={!!errors.password}
            helperText={errors.password ? errors.password?.message : ""}
          />
        )}
      />
      <br />
      <br />
      <input type="submit" />
    </form>
  );
}

```

## 終わりに
以上になります。最後まで読んでくださりありがとうございました。

※part4があれば、formProviderについて書きます。