ReactHookFormとzodをプロジェクトに導入しました!

Posted date at 2024-04-29

React

 

ReactHookForm.png

zod.png

「ユーザが指定した時刻にメールを送信するシステムを開発しました!」で少し触れましたが、メール送信設定の入力フォームにはReactHookFormzodという新しいライブラリを使用しています。

 

〇これまでの実装方法

  • 入力状態の管理⇒useStateとuseEffectを使用
  • バリデーションチェック⇒自前でコーディング(場合によっては正規表現を使用)

 

〇今回の実装方法

  • 入力状態の管理⇒ReactHookFormを使用(状態監視)
  • バリデーションチェック⇒zodを使用(ルールの定義)

 

〇ReactHookFormとzodを使用する上で参考にした動画(リンク)

 

■ReactHookForm

React Hook Formは、Reactアプリケーションでフォームを簡単に扱うためのライブラリです。このライブラリを使うことで、フォームの状態管理やバリデーション(入力値の検証)がシンプルになり、パフォーマンスも向上します。

NextSHIFTにおける記述抜粋

「フォームの初期化」

useFormを使用して、フォームを初期化する。resolverプロパティには後述するzodで定義したバリデーションスキーマ(ここではエラーチェックのルールのこと)をセットする。

//ReactHookFormの定義 const { control, handleSubmit, formState: { errors }, trigger, watch, reset, setValue, } = useForm({ mode: "all", resolver: zodResolver(mailAddSchema), defaultValues: { workerId: "", workerName: "", email: "", isSend: "する", isZeroSend: "しない", sendTime: "16:00", }, });

 

「状態監視」

状態監視はwatchを使用する。ユーザからの入力でwatchで指定したフィールドの内容が変化する。これがuseStateの代わりなっていると考えていい。

const watchAllFields = watch(); const watchSendTime = watch("sendTime"); const watchEmail = watch("email"); //デバッグのための記述 useEffect(() => { console.log(watchAllFields, watchSendTime, "errors", errors); }, [watchAllFields]); //メール重複解除のための記述 useEffect(() => { setIsDuplicate(false); }, [watchEmail]);

 

「フォームへの適用-テキストフィールド」

まず、ReactHookFormを使用する場合は、フォームタグを使用する必要がある。なので、ボタン要素にもtype属性でsubmitを指定して、onSubmitイベントを発生させる必要がある。イベントが発火するとhandleSubmitの引数に指定したコールバック関数(下記の場合、handleAddButtonClick)が実行される。なお、バリデーションにエラーがあるとき(「errors」がnullでないとき)はコールバックは実行されない。

入力要素(ここではテキストフィールド)への適用は、Controllerタグで囲ってやり、render関数内で、fieldを指定すれば良い。このfieldには入力された値が格納されると考えて良い。

<form onSubmit={handleSubmit(handleAddButtonClick)}> <div className={classes.inputStandard}> <Controller name="workerId" control={control} render={({ field }) => ( <TextField label="社員番号" variant="outlined" type="number" {...field} sx={inputOutlinedStyle("workerNo")} onBlur={(e) => handleBlurWorkerId(e)} placeholder="01234" InputLabelProps={{ shrink: true, }} error={!!errors.workerId} // バリデーションエラー判定 helperText={errors.workerId?.message} // エラーメッセージ表示 /> )} /> </div> <div className={classes.buttons}> <Button variant="contained" type="submit" sx={getStyles("yesColor")} > 登録 </Button> </div> </form>

 

「強制的に要素の値を変更する方法」

setValueにフィールド名と値を指定すると、意図的にフィールド(上記のfield)の値を変更できる。

またtriggerを使用することで、指定したフィールドが変更されたというイベント発火させることができる。以下は、社員番号を入力し、フォーカスがはずれたときに、社員情報を取得して、社員名とメールアドレスをセットして、再レンダリングする処理である。

const handleBlurWorkerId = async (e) => { const value = e.target.value; if (value.length > 0 && value.length <= 5) { const res = await getWorkerinfo(value); console.log(res); if (res) { setValue("email", res[6]); setValue("workerName", res[0]); trigger("workerName"); trigger("email"); } else { setValue("workerName", ""); setValue("email", ""); trigger("workerName"); trigger("email"); } } };

 

「リセット」

以下の記述でリセットが可能である。submitが行った後などに記述する。

reset({ workerId: "", workerName: "", email: "", isSend: "する", isZeroSend: "しない", sendTime: "16:00", });

 

■zod

ZodはTypeScriptで使うためのスキーマ検証ライブラリで、入力値のバリデーションを行いながら、その入力値に適した型情報を自動的に提供することができます。このライブラリをReact Hook Formと組み合わせることで、フォームのバリデーションロジックを強化し、型安全性を高めることができるという大きな利点があります。

また、TypeScriptでなくても、

  1. 簡潔なバリデーションコード: Zodを使用すると、バリデーションロジックを簡潔に書くことができます。これにより、コードの可読性とメンテナンス性が向上します。
  2. 自動化されたエラーハンドリング: React Hook FormとZodを組み合わせることで、フォームの入力値がZodスキーマに適合しない場合に自動的にエラーメッセージを表示することができます。

により、バリデーションロジックを簡潔にかつzodに任せることができます。

 

NextSHIFTにおける記述(抜粋)

「スキーマの生成」

以下のようにバリデーションをオブジェクトで定義することができる。型指定、文字数の他、リスト(列挙)、メールアドレスも指定できる。

import { z } from "zod"; import { timeTableForMailonValidation } from "../../../../commons/timeTable"; const timeList = timeTableForMailonValidation(); export const mailAddSchema = z.object({ workerId: z.string().max(5, "最大5文字"), workerName: z.string().min(1, "氏名は必須です"), email: z .string() .min(1, "メールアドレスは必須です") .email("無効なメールアドレス"), isSend: z.enum(["する", "しない"]), isZeroSend: z.enum(["する", "しない"]), sendTime: z.enum(timeList), });

 

「ReactHookFormへの適用」

useFormのresolverで指定することで適用可能である。

//ReactHookFormの定義 const { control, handleSubmit, formState: { errors }, trigger, watch, reset, setValue, } = useForm({ mode: "all", resolver: zodResolver(mailAddSchema), defaultValues: { workerId: "", workerName: "", email: "", isSend: "する", isZeroSend: "しない", sendTime: "16:00", }, });

 

以上となります。簡単ですが、大まかな使用の流れは説明できたかなと思います。詳細はドキュメントや上記の動画、ブログなどを参考に実装する中で掴んでください。

←ホームに戻る