はじめに
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="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=""などを指定することで回避できます。
全体のコード
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について書きます。