📑
【MUI×Zod×RHF】複数のチェックボックス群にバリデーションさせたい
はじめに
実際の業務で初めてMUIで構成されたReactHookFormをZodで管理することになり、
つまづいたので備忘録として残しておく
前提知識
MUI
- コンポーネントライブラリの1つ。スタイルつきで簡単に統一したレイアウトが作成できる。
- MUIのコンポーネントには
ContorolledComponent
とUnContorolledComponent
という概念がある。 -
ContorolledComponent
とはstateなどの状態によって変化させるコンポーネントのことであり、入力フォームなどは基本的にContorolledComponent
になる。
Zod
- TS向けのバリデーションスキーマライブラリ
- 型定義と実行時チェックを一括で行えるのが強み
RHF(React Hook Form)
- React向けのフォーム管理ライブラリ
- 最小限のレンダリング、ZodやYupなどのバリデーションとの連携が簡単
やりたいこと
以下のParents.tsx
にChildren
というコンポーネントを配置し、
Children
というコンポーネントに複数のチェックボックスを作成。
Children
内の複数チェックボックス全体に対して、バリデーションを実装したい。
Parents.tsx
import { z } from "zod";
import { FormProvider, useForm } from "react-hook-form";
import { Box } from "@mui/material";
import Children from "~hogehoge";
const Schema = z.object({
checkBox : z.array(z.number()).superRefine((a,index)=>{
//やりたいバリデーションルール
message : "エラーメッセージ",
}),
export type ValidationShemaType = z.infer<typeof Schema>;
const Parents = () {
const methods = useForm<ValidationShemaType>({
mode : "onChange",
resolver : zodResolver(ValidationShemaType),
defaultValues :{
checkBox : [],
}
});
return (
<FormProvider {...methods}>
<Box component={"form"} submitAction={onSubmit}>
<Children user={userData} />
</Box>
</FormProvider>
);
export default Parents;
実際のコード
Children.tsx
import { ValidationShemaType } from "../Parents";
import { Controller, useFormContext } from "react-hook-form";
import { FormGroup, FormContorolLabel, Checkbox } from "@mui/material";
type Props =hogehoge;
const Children = ({user}:Props) {
const { contorol, formState: { erros } , } = useFormContext<ValidationShemaType>;
};
return (
<FormGroup>
<Controller
name="checkBox"
control={contorol}
render={({field}) =>{
<>
//レンダーさせたいチェックボックス群.map((hoge) => (
<FormContorolLabel
key={hoge.id}
contorol={
<CheckBox>
/>
))}
{erros.checkBox && (
<div style={{color:"red"}}>
{erros.checkBox.message}
</div>
)}
</>
)}
/>
</FormGroup>
);
export default Children;
まとめ
- RHFで、MUIなどの外部のUIコンポーネントライブラリを管理したいとき、
Contoroller
を使う - RHF内のフォームのname属性と、Zodで定義したスキーマの属性名は揃える
- RHFの
FormProvider
は囲まれているコンポーネント内でRHFのメソッド、プロパティにアクセスできる-
FormProvider
利用側はuseFormContext
を介して利用する
-
課題
今回はRHFのContoroller
とMUIを組み合わせたが、Contoroller
なしでも実装できるようなので調べてみたい
Discussion