FrontEnd

Remixでフォーム作るならConformが良いらしいので試してみた

投稿日:

はじめに

最近、Remixをいじり始めました。その中でFormの実装にはConformというライブラリを使った方が良い、という情報が多かったので、実際どうなのか試してみました。

まずは、Remixでベーシックなフォームとバリデーションを作り、今度はそれをConformを使って作ってみる、という方法で比較してみたいと思います。

Conformを使わずにフォームを実装

サンプル実装

まずは、loaderまで実装します。

loaderでは、データベースを模したconst profileDB をそのまま返すのみです。

次に、actionを実装します。

actionはサーバサイドで実行されるため、リクエストされてきた値にはバリデーションをかける必要があります。

まず、フォームの値は formData.get("name") のように取得できるのですが、この時点での型は File | string | null となっています。
今回のフォームは文字列であるため、 ?.toString() することでひとまず string | null になります。
数値や日時も一旦 string になってしまうため、必要に応じてパースする必要があります。

バリデーションでは、必須チェックと文字数チェックをしています。チェックに引っかかった場合は、 return json() でメッセージをレスポンスします。

バリデーションが全て通った場合のみ、データを保存し、メッセージをレスポンスして終了です。

最後に、コンポーネントのコードです。

Joy UIを使っていますが、シンプルなフォームになっています。

先ほどのactionのレスポンスを表示するため、 useActionData<typeof action>() を使っています。

また、クライアントでのバリデーションはHTMLの標準機能を使っています。基本的にはこのバリデーションが効いているため、サーバサイドでバリデーションエラーとなることはありませんが、このバリデーションを外すことで、actionのバリデーションを試すことができます。

このコードの辛い点

ひとまず、Remixのドキュメントを参考にしながらこのコードを書いてみて、以下の点が辛いなと思いました。

  • actionで受け取ることができるフォームの型が File | string | null となっていて、数値や日付の場合はパースする必要がある
  • actionとコンポーネントで、同じバリデーションルールをそれぞれ書く必要がある

サーバサイドとクライアントサイドが別のアプリケーションである場合は、スキーマ駆動開発によってこの2点を解消することができると思います。
Remixの場合は、こういった辛い点をConformを使って乗り切るみたいです。

Conformを使ってみる

ConformはRemixやNext.jsに対応する、型安全なフォームバリデーションライブラリです。バリデーション部分はZodに依存しているのですが、actionやコンポーネントの実装に便利な関数が用意されていて、Remixとうまく統合することができるみたいです。
実際に試してみましょう。

サンプルコード

それでは先ほどのフォームをConformを使って実装してみます。loaderまでは同じなので省略し、actionから進めます。

Conformを使うと、 z.object() によって生成されるZodのスキーマ定義に従ってバリデーションされます。
そのため、 parseWithZod() を使うだけで、バリデーションができます。

さらに、その戻り値を使い、 submission.reply() を返すことで、バリデーション結果をレスポンスすることができます。
このバリデーション結果は、あとで登場する、コンポーネント用のhook useForm に渡すことで、クライアント側でもエラー内容を取り扱うことができます。

最後に、コンポーネント側のコードです。

actionDataとloaderDataをもらうところまでは同じですね。

その後、 useForm というConformのフックを使います。このhookを使うと、次のことができるようになります。

  • クライアントサイドでのフォームバリデーション
  • サーバサイドバリデーションの結果をパース

先ほどとは異なり、バリデーションエラーは fields.name.errors のように、項目ごとに取得できるようになるので、項目ごとのヘルパーテキストとして表示するようにしてみました。

また、Formコンポーネントに {...getFormProps(form)} を渡すことで、フォーム送信前にクライアント側でのバリデーションが効くようになります。今回は、形式チェックのみなので、クライアントのバリデーションのみで引っかかってくれるのですが、この関数を外すことで、サーバサイドのバリデーションが効いていることを確認することができます。

さいごに

ConformはZodとRemixをうまく連携してくれることが分かりました。それ故に隠蔽された部分も感じられたのですが、それ以上にバリデーションのコードが短くなることが嬉しかったので、これは実践でも使ってみて良いかなと思いました。

おすすめ書籍

Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

blog-page_footer_336




blog-page_footer_336




-FrontEnd

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

正式版Vue.js 3.0のTeleportを触ってみる

1 はじめに1.1 Vue.js 3.0のプロジェクト作成方法1.2 Teleportとは2 基本形2.1 コード2.2 画面3 別のコンポーネントの入れ子にする場合3.1 コード3.2 画面4 同じ ...

Vue.js入門その7〜セレクトボックスを動的に変更してみる〜

1 はじめに1.1 サンプル2 とりあえず作ってみる2.1 ソースコード2.2 セレクトボックスにv-modelでバインド2.3 <option>はv-forでリストレンダリング2.4 メ ...

tailwindcss

Tailwind CSSの基礎とVue.jsへの導入

1 はじめに2 Tailwind CSSとは2.1 utility class3 Bootstrapとの比較3.1 柔軟性3.2 コード量3.3 学習コスト3.4 ファイルサイズ3.5 その他4 なぜ ...

[Rails + Materialize] DateTimePickerがなかったので…

1 はじめに2 前提条件2.1 ビューのイメージ3 モデルにゲッターとセッターを追加4 入力フォームに追加4.1 JSファイルにて使用宣言4.2 HTML4.3 コントローラーのストロングパラメータを ...

js

Vue.jsをTypeScriptで安全に開発するためのtsconfig.json

1 はじめに1.1 開発環境1.2 プロジェクト作成時点のtsconfig.json2 include3 exclude4 compilerOptions4.1 コンパイル系オプション4.1.1 ta ...

フォロー

blog-page_side_responsive

2024年10月
 12345
6789101112
13141516171819
20212223242526
2728293031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。