【Tanstack Form】送信試行後のみonChange検証する【React】

こんにちは、フリーランスエンジニアの太田雅昭です。

Tanstack FormのonChange

Tanstack Formでのバリデーションは、フィールドごとにどのイベントで発火させるかなどわかりやすいAPIとなっています。

送信試行後のみonChangeする

ユーザー体験向上のため、下記のような動作にします。

  • メールアドレスを入力
  • 送信試行
  • エラー表示。以降は入力に追従してエラーが変化する

公式の方法

公式で紹介されているのは、onDynamicを使った方法です。下記ではzodを使用しています。

const form = useForm({
  validationLogic: revalidateLogic({
    mode: 'submit',
    modeAfterSubmission: 'change',
  }),
  ...

...

<form.Field
      validators={{
        onDynamic: ({value}) => z
            .email('有効なメールアドレスを入力してください')
            .max(200, '200文字以内で入力してください'))
            .safeParse(value).error?.issues[0]?.message
      ...
      }}

初期モードはonSubmit, 送信後はonChangeに切り替わります。便利。

オレオレの方法

下記は非推奨の方法です。

以下のようなユーティリティを作ります。zodを使用しています。

type ValidateParams = { value: any, fieldApi: AnyFieldApi }

export function createZodValidator(
  schema: z.ZodSchema,
  options?: { onlyAfterAttempts?: boolean }
) {
  return ({ value, fieldApi }: ValidateParams) => {
    if (options?.onlyAfterAttempts && fieldApi.form.state.submissionAttempts === 0) {
      return undefined;
    }
    return schema.safeParse(value).error?.issues[0]?.message
  }
}

これを使用して、以下のようにします。

<form.Field
  name="age"
  validators={{
    onChange: createZodValidator(
      z.email('有効なメールアドレスを入力してください'),
      { onlyAfterAttempts: true })
  }}
>
  {(field) => (
    <>
      ...
    </>
  )}
</form.Field>