💬

MantineのuseFormでzodを活用する場合のtips

2023/06/02に公開

MantineのuseFormでzodを活用して開発をする中で、注意点や便利な活用方法を記事にします。

transformValuesでparse()

useFormでzodを活用する場合は、基本的に毎回useFormで以下のコードを入れるようにしています。

transformValues: (values) => schema.strip().parse(values)

parseを行うことで、不要な値が削除された結果が返却されます。
stripはschemaにstrictを付与していた場合でも、結果を返却するデフォルトの挙動に戻すオプションです。
strictだと不要な項目がある場合はエラーとして扱われます。

これの恩恵を受けるのは具体的に2点あります。

  1. 不要な項目をリクエストに設定しない
  2. trimなどが反映された状態になる

1点目に関して、useFormのinitialValuesにはAPIで取得したデータ(それを画面用に変換したもの)を設定することが多いと思いますが、必ずしもその全てを更新リクエストとして設定したいわけではないと思います。
zod定義=リクエスト項目にはなると思うので、transformValuesでparseするのが可読性/コストの観点から最も良いと思います。

2点目に関して、react-hook-formでは、以下のようなzodでの変換がデフォルト反映された状態で扱われます。

z
 .string()
 .trim()

しかし、MantineのuseFormではzodResolverはvalidateにしか効果を持たないため、リクエストにtrimなどを反映させたい場合は、transformValuesでparseさせてあげる必要があります。

transformValuesの型にinferを活用する

基本的にtransformValuesの型はinterfaceの型があれば、そちらを適用するべきと思います。
ただ、interfaceを用意していなかったり、場合によっては適用できないこともあると思い、そのときはinferを活用してあげると良いです。

UseFormReturnType<getModel, (values: getModel) => z.infer<typeof schema>>

z.inferは作成したスキーマから型を取り出すことができます。

zodでrefineを活用する際、useEffectが必要

相関チェックなどでrefineを活用することがあると思います。
refineを活用し、かつ配列のスキーマの場合、validateInputOnChangeをtrueにしていても即時でエラーメッセージが反映されません。

対処法としては、useEffectでform.validate()を実行してあげることです。

  useEffect(() => {
    form.validate()
    return () => form.clearErrors()
    // formを依存に入れると過度なレンダリングとなるため、disableしている
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [form.values])

まとめ

useFormとzodの相性は良いので、Mantineを活用する場合は導入することをお勧めします!
他にも便利な使い方などあれば、コメントで共有いただけると嬉しく思います。

Discussion