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します。

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から取得できます。

  const {control} = useForm();
  • render renderには関数を指定します。指定した関数はfieldを受け取ります。fieldにはcontrolで指定したpropsの値が入っています。また、指定した関数はMUIを返します。 以下の例では戻り値のMUIとしてTextFieldを返しています。また、TextFieldのpropsにはfieldをスプレッドして指定します。こうすることで、MUIのvalue値をRHFで取得できるようになります。
 render={({ field }) => (
          <TextField
            {...field}
          />
        )}

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

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

エラーメッセージの出力

あとはエラーメッセージを出せるようにします。part2の知識があればココを読まなくても書けそうですね。
以下の例のコードではemailの入力を受け付けるMUIとして定義しています。

※テキストフィールドの右の3点リーダーと丸のやつはNortonが勝手に表示しているやつです。

<Controller
        name="email"
        control={control}
        defaultValue="[email protected]"
        render={({ field }) => (
          <TextField
            {...field}
            type="email"
            label="Email"
            variant="outlined"
            error={!!errors.email}
            helperText={errors.email ? errors.email?.message : ""}
          />
        )}
      />

注意点

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

全体のコード

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="[email protected]"
        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について書きます。