スキーマライブラリの共通インターフェイスを提供するStandard Schema v1をご紹介
Standard Schemaのv1がリリースされたので触ってみた。
Standard Schema とは
現在バリデーションライブラリとしてzodや valibot、arktypeなどがありますが、それらをTanStack Formなどの別ライブラリと統合して使用する際には専用のadapterを使用する必要がありました。以下のコードはTanStack Formとzodを組み合わせた時の例です。
import { useForm } from "@tanstack/react-form";
// zod用のadapterをインストールする必要がある
import { zodValidator } from "@tanstack/zod-form-adapter";
import { z } from "zod";
const userSchema = z.object({
name: z.string(),
});
export function Form() {
const form = useForm({
defaultValues: {
name: "",
},
// zodValidatorをセットする
validatorAdapter: zodValidator(),
validators: {
onChange: userSchema,
},
onSubmit: (values) => {
console.log(values);
},
});
return (
<form onSubmit={form.handleSubmit}>
<form.Field
name="name"
children={(field) => (
<div>
<label htmlFor={field.name}>Name:</label>
<input
id={field.name}
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
</div>
)}
/>
<button type="submit">Submit</button>
</form>
);
}
また、TanStack Formではこのadapterがzod、yup、valibotのものしかなく、それ以外のバリデーションライブラリと組み合わせることはできませんでした(後述しますが、最新のTanStack FormはStandard Schemaを受け入れているため、他のライブラリも使えます)。
しかしなぜ、各バリデーションライブラリ専用のadapterが必要なのでしょうか。それは各ライブラリごとにinterfaceが違うからです。そこで登場したのがStandard Schemaです。
Standard Schemaはバリデーションライブラリの共通インターフェースを定義し、その定義に沿って各バリデーションライブラリが実装することにより、ライブラリに互換性を持たせ、1つのadapterでさまざまなバリデーションライブラリを使用できるようにすることを目的としています。
Standard Schemaの使い方
READMEにも書かれているシンプルな使い方を紹介します。まず、standardValidateという関数を定義します。
次にStandard Schemaのインターフェースを実装しているライブラリでスキーマを定義します。
そして、standardValidateとスキーマを組み合わせ、以下のonSubmit関数の中で行なっているようにバリデーションを実行することができます。
standardValidateの第2引数にはStandard Schemaのインターフェースを実装しているライブラリであれば、どのライブラリでも使用できるため、ライブラリの差し替えが容易になります。
各ライブラリの対応
Standard Schemaを実装しているバリデーションライブラリと、Standard Schemaをサポートしているライブラリは以下に記載されています。
TanStack Form
初めの方でTanStack Formとzodの組み合わせの例を紹介しましたが、TanStack FormもStandard Schemaをサポートしており、現在の最新のバージョンでは@tanstack/zod-form-adapter
のようなライブラリを使用する必要はなくなりました。また、組み合わせることのできるバリデーションライブラリもStandard Schemaを実装しているバリデーションライブラリであれば自由に選べるようになりました。
以下がStandard Schemaを利用したときの例です。差分としては@tanstack/zod-form-adapter
を削除しただけです。
import { useForm } from "@tanstack/react-form";
- // zod用のadapterをインストールする必要がある
- import { zodValidator } from "@tanstack/zod-form-adapter";
import { z } from "zod";
const userSchema = z.object({
name: z.string(),
});
export function Form() {
const form = useForm({
defaultValues: {
name: "",
},
- // zodValidatorをセットする
- validatorAdapter: zodValidator(),
validators: {
onChange: userSchema,
},
onSubmit: (values) => {
console.log(values);
},
});
return (
<form onSubmit={form.handleSubmit}>
<form.Field
name="name"
children={(field) => (
<div>
<label htmlFor={field.name}>Name:</label>
<input
id={field.name}
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
</div>
)}
/>
<button type="submit">Submit</button>
</form>
);
}
これにより、Standard Schemaをサポートする前のTanStack Formではzod、valibot、yupしか選べませんでしたが、サポート後はArkType、Arri Schema、TypeMapも使えるようになりました。今後もStandard Schemaを実装するバリデーションライブラリが増えれば、さらに色々なバリデーションライブラリを使えるようになるでしょう。
まとめ
Standard Schemaの登場により、adapterのようなglueなライブラリが必要なくなり、ライブラリの組み合わせの自由度が増しました。今後、Standard Schemaを実装/サポートするライブラリが増えることでバリデーションライブラリの乗り換えなども楽になりそうだなと思っており、楽しみです。
追記
自分がよく使うフォームライブラリであるReact Hook Formが対応してなかったので実装しました
Discussion