useFormのmode復習とtriggerについて
useFormのmode:"onBlur"を利用したら、errorsにオブジェクトが格納されない
複数のコンポーネントをまとめた情報入力画面で、必須選択項目にバリデーションチェックを行い、未選択の場合はerrorsに格納するようにした。情報入力画面下部の「次へ」ボタンを押すと未選択の項目がフォーカスされ、赤枠で表示される予定。しかし1回目で「次へ」ボタンを押すとフォーカスが実行されない。別コンポーネントの選択項目を選択し直すなどすると、フォーカスが実行される。確認してみると、フォーカスが実行されないときはerrorsにオブジェクトが格納されていないことがわかった。(1回「次へ」ボタンを押して、選択し直すと2回目以降はerrorsに格納される。)
オブジェクト定義はこんな感じ
const methods = useForm({
defaultValues: {
workerCd: state.report.workerCd,
workDateForm: state.report.workDateForm,
workDay: state.report.workDay
? state.report.workDay
: formatDateToString(new Date()),
workTime: state.report.workTime,
},
// フォーカスが外れたタイミングでバリデーションをチェック
mode: "onBlur",
// Submit後のバリデーション
reValidateMode: "onBlur",
// 入力エラー時エラー先頭項目にフォーカスがあたらないため手動でフォーカス設定
shouldFocusError: false,
});
ここで一旦useForm(mode)の復習。
useFormを使うとフォームの状態管理やバリデーションルールが柔軟かつ簡単に設定できる。
modeは初回フォーム送信時(handleSubmit)のバリデーションの実行タイミングを細かく設定することができる。
・onSubmit / 送信時 (初期値)
・onBlur / 対象の不フィールドからフォーカスを外したタイミング
・onChange / 入力項目が変更されたとき
・all / onBlur, onChange時
最初、modeの"onBlur"が原因かと思ってその他のプロパティ(onChange, all...)も試してみたけど改善しなかった。だがタイミングの問題であることは明らか。
そこで、次へボタン押下タイミング(handleOnClickNext関数内)の最初にtriggerを設定してみた。
triggerとは
フォームやinputのバリデーションを手動で発動させることができる関数。入力が他の入力項目と依存関係にある項目のバリデーションチェックにも役に立つそう。
引数の取り方と意味はこんな感じ
・未定義:全てのフィールドでバリデーションをトリガー
trigger()
・String:nameの指定によって特定の項目の単一の値のバリデーションをトリガー
trigger("yourDetails.firstName")
・String[]:nameの指定によって複数の項目のバリデーションをトリガー
trigger(["yourDetails.lastName"])
・boolean(shouldFocus):エラー設定時に入力にフォーカスするかどうかを決められる
trigger('name', { shouldFocus: true })
こんな感じ
const handleOnClickNext = () => {
// バリデーションエラー時にフォーカスされない場合があるため手動のトリガーを設定
trigger();
setPushedNextButton(true);
}
今回は複数コンポーネントにわたる入力項目すべてに対してバリデーションをトリガーしたかったので、allで対応。公式ドキュメントでは場所的にbutton, onClickでtriggerを設定することが推奨されてるのかな??
return (
<form>
<input {...register("firstName", { required: true })} />
<input {...register("lastName", { required: true })} />
<button
type="button"
onClick={() => {
trigger()
}}
>
Trigger All
</button>
</form>
)
何はともあれ、しっかり1回目でerrorsに格納されましたとさ。
Discussion