ReactHookFormとzodをプロジェクトに導入しました!
Posted date at 2024-04-29
「ユーザが指定した時刻にメールを送信するシステムを開発しました!」で少し触れましたが、メール送信設定の入力フォームにはReactHookFormとzodという新しいライブラリを使用しています。
〇これまでの実装方法
- 入力状態の管理⇒useStateとuseEffectを使用
- バリデーションチェック⇒自前でコーディング(場合によっては正規表現を使用)
〇今回の実装方法
- 入力状態の管理⇒ReactHookFormを使用(状態監視)
- バリデーションチェック⇒zodを使用(ルールの定義)
〇ReactHookFormとzodを使用する上で参考にした動画(リンク)
- 【『React』×『TypeScrip』入門 】家計簿アプリ作成でReactとTypeScriptの開発方法を学ぼう
- 【react-hook-form入門】超簡単にログインフォームを作る方法を発見したので解説します【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でなくても、
- 簡潔なバリデーションコード: Zodを使用すると、バリデーションロジックを簡潔に書くことができます。これにより、コードの可読性とメンテナンス性が向上します。
- 自動化されたエラーハンドリング: 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", }, });
以上となります。簡単ですが、大まかな使用の流れは説明できたかなと思います。詳細はドキュメントや上記の動画、ブログなどを参考に実装する中で掴んでください。
←ホームに戻る