- Notifications
You must be signed in to change notification settings - Fork179
📋 Validation resolvers: Yup, Zod, Superstruct, Joi, Vest, Class Validator, io-ts, Nope, computed-types, typanion, Ajv, TypeBox, ArkType, Valibot, effect-ts, VineJS and Standard Schema
License
react-hook-form/resolvers
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Performant, flexible and extensible forms with easy to use validation.
This function allows you to use any external validation library such as Yup, Zod, Joi, Vest, Ajv and many others. The goal is to make sure you can seamlessly integrate whichever validation library you prefer. If you're not using a library, you can always write your own logic to validate your forms.
Install your preferred validation library alongside@hookform/resolvers
.
npm install @hookform/resolvers # npmyarn add @hookform/resolvers # yarnpnpm install @hookform/resolvers # pnpmbun install @hookform/resolvers # bun
Resolver Comparison
resolver | Infer values from schema | criteriaMode |
---|---|---|
AJV | ❌ | `firstError |
Arktype | ✅ | firstError |
class-validator | ✅ | `firstError |
computed-types | ✅ | firstError |
Effect | ✅ | `firstError |
fluentvalidation-ts | ❌ | firstError |
io-ts | ✅ | firstError |
joi | ❌ | `firstError |
Nope | ❌ | firstError |
Standard Schema | ✅ | `firstError |
Superstruct | ✅ | firstError |
typanion | ✅ | firstError |
typebox | ✅ | `firstError |
typeschema | ❌ | `firstError |
valibot | ✅ | `firstError |
vest | ❌ | `firstError |
vine | ✅ | `firstError |
yup | ✅ | `firstError |
zod | ✅ | `firstError |
type Options = { mode: 'async' | 'sync', raw?: boolean}resolver(schema: object, schemaOptions?: object, resolverOptions: Options)
type | Required | Description | |
---|---|---|---|
schema | object | ✓ | validation schema |
schemaOptions | object | validation library schema options | |
resolverOptions | object | resolver options,async is the default mode |
Dead simple Object schema validation.
import{useForm}from'react-hook-form';import{yupResolver}from'@hookform/resolvers/yup';import*asyupfrom'yup';constschema=yup.object().shape({name:yup.string().required(),age:yup.number().required(),}).required();constApp=()=>{const{ register, handleSubmit}=useForm({resolver:yupResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('name')}/><inputtype="number"{...register('age')}/><inputtype="submit"/></form>);};
TypeScript-first schema validation with static type inference
⚠️ Example below uses thevalueAsNumber
, which requiresreact-hook-form
v6.12.0 (released Nov 28, 2020) or later.
import{useForm}from'react-hook-form';import{zodResolver}from'@hookform/resolvers/zod';import{z}from'zod';constschema=z.object({name:z.string().min(1,{message:'Required'}),age:z.number().min(10),});constApp=()=>{const{ register, handleSubmit,formState:{ errors},}=useForm({resolver:zodResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('name')}/>{errors.name?.message&&<p>{errors.name?.message}</p>}<inputtype="number"{...register('age',{valueAsNumber:true})}/>{errors.age?.message&&<p>{errors.age?.message}</p>}<inputtype="submit"/></form>);};
A simple and composable way to validate data in JavaScript (or TypeScript).
import{useForm}from'react-hook-form';import{superstructResolver}from'@hookform/resolvers/superstruct';import{object,string,number}from'superstruct';constschema=object({name:string(),age:number(),});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:superstructResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('name')}/><inputtype="number"{...register('age',{valueAsNumber:true})}/><inputtype="submit"/></form>);};
The most powerful data validation library for JS.
import{useForm}from'react-hook-form';import{joiResolver}from'@hookform/resolvers/joi';importJoifrom'joi';constschema=Joi.object({name:Joi.string().required(),age:Joi.number().required(),});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:joiResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('name')}/><inputtype="number"{...register('age')}/><inputtype="submit"/></form>);};
Vest 🦺 Declarative Validation Testing.
import{useForm}from'react-hook-form';import{vestResolver}from'@hookform/resolvers/vest';import{create,test,enforce}from'vest';constvalidationSuite=create((data={})=>{test('username','Username is required',()=>{enforce(data.username).isNotEmpty();});test('password','Password is required',()=>{enforce(data.password).isNotEmpty();});});constApp=()=>{const{ register, handleSubmit, errors}=useForm({resolver:vestResolver(validationSuite),});return(<formonSubmit={handleSubmit((data)=>console.log(data))}><input{...register('username')}/><inputtype="password"{...register('password')}/><inputtype="submit"/></form>);};
Decorator-based property validation for classes.
⚠️ Remember to add these options to yourtsconfig.json
!
"strictPropertyInitialization": false,"experimentalDecorators": true
import{useForm}from'react-hook-form';import{classValidatorResolver}from'@hookform/resolvers/class-validator';import{Length,Min,IsEmail}from'class-validator';classUser{ @Length(2,30)username:string; @IsEmail()email:string;}constresolver=classValidatorResolver(User);constApp=()=>{const{ register, handleSubmit,formState:{ errors},}=useForm<User>({ resolver});return(<formonSubmit={handleSubmit((data)=>console.log(data))}><inputtype="text"{...register('username')}/>{errors.username&&<span>{errors.username.message}</span>}<inputtype="text"{...register('email')}/>{errors.email&&<span>{errors.email.message}</span>}<inputtype="submit"value="Submit"/></form>);};
Validate your data with powerful decoders.
importReactfrom'react';import{useForm}from'react-hook-form';import{ioTsResolver}from'@hookform/resolvers/io-ts';importtfrom'io-ts';// you don't have to use io-ts-types, but it's very usefulimportttfrom'io-ts-types';constschema=t.type({username:t.string,age:tt.NumberFromString,});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:ioTsResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/><inputtype="number"{...register('age')}/><inputtype="submit"/></form>);};exportdefaultApp;
A small, simple, and fast JS validator
import{useForm}from'react-hook-form';import{nopeResolver}from'@hookform/resolvers/nope';importNopefrom'nope-validator';constschema=Nope.object().shape({name:Nope.string().required(),age:Nope.number().required(),});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:nopeResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('name')}/><inputtype="number"{...register('age')}/><inputtype="submit"/></form>);};
TypeScript-first schema validation with static type inference
import{useForm}from'react-hook-form';import{computedTypesResolver}from'@hookform/resolvers/computed-types';importSchema,{number,string}from'computed-types';constschema=Schema({username:string.min(1).error('username field is required'),age:number,});constApp=()=>{const{ register, handleSubmit,formState:{ errors},}=useForm({resolver:computedTypesResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('name')}/>{errors.name?.message&&<p>{errors.name?.message}</p>}<inputtype="number"{...register('age',{valueAsNumber:true})}/>{errors.age?.message&&<p>{errors.age?.message}</p>}<inputtype="submit"/></form>);};
Static and runtime type assertion library with no dependencies
import{useForm}from'react-hook-form';import{typanionResolver}from'@hookform/resolvers/typanion';import*astfrom'typanion';constisUser=t.isObject({username:t.applyCascade(t.isString(),[t.hasMinLength(1)]),age:t.applyCascade(t.isNumber(),[t.isInteger(),t.isInInclusiveRange(1,100),]),});constApp=()=>{const{ register, handleSubmit,formState:{ errors},}=useForm({resolver:typanionResolver(isUser),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('name')}/>{errors.name?.message&&<p>{errors.name?.message}</p>}<inputtype="number"{...register('age')}/>{errors.age?.message&&<p>{errors.age?.message}</p>}<inputtype="submit"/></form>);};
The fastest JSON validator for Node.js and browser
import{useForm}from'react-hook-form';import{ajvResolver}from'@hookform/resolvers/ajv';// must use `minLength: 1` to implement required fieldconstschema={type:'object',properties:{username:{type:'string',minLength:1,errorMessage:{minLength:'username field is required'},},password:{type:'string',minLength:1,errorMessage:{minLength:'password field is required'},},},required:['username','password'],additionalProperties:false,};constApp=()=>{const{ register, handleSubmit,formState:{ errors},}=useForm({resolver:ajvResolver(schema),});return(<formonSubmit={handleSubmit((data)=>console.log(data))}><input{...register('username')}/>{errors.username&&<span>{errors.username.message}</span>}<input{...register('password')}/>{errors.password&&<span>{errors.password.message}</span>}<buttontype="submit">submit</button></form>);};
JSON Schema Type Builder with Static Type Resolution for TypeScript
import{useForm}from'react-hook-form';import{typeboxResolver}from'@hookform/resolvers/typebox';import{Type}from'@sinclair/typebox';constschema=Type.Object({username:Type.String({minLength:1}),password:Type.String({minLength:1}),});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:typeboxResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/><inputtype="password"{...register('password')}/><inputtype="submit"/></form>);};
A high-performance JIT ofTypeBox
,read more
import{useForm}from'react-hook-form';import{typeboxResolver}from'@hookform/resolvers/typebox';import{Type}from'@sinclair/typebox';import{TypeCompiler}from'@sinclair/typebox/compiler';constschema=Type.Object({username:Type.String({minLength:1}),password:Type.String({minLength:1}),});consttypecheck=TypeCompiler.Compile(schema);constApp=()=>{const{ register, handleSubmit}=useForm({resolver:typeboxResolver(typecheck),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/><inputtype="password"{...register('password')}/><inputtype="submit"/></form>);};
TypeScript's 1:1 validator, optimized from editor to runtime
import{useForm}from'react-hook-form';import{arktypeResolver}from'@hookform/resolvers/arktype';import{type}from'arktype';constschema=type({username:'string>1',password:'string>1',});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:arktypeResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/><inputtype="password"{...register('password')}/><inputtype="submit"/></form>);};
The modular and type safe schema library for validating structural data
import{useForm}from'react-hook-form';import{valibotResolver}from'@hookform/resolvers/valibot';import*asvfrom'valibot';constschema=v.object({username:v.pipe(v.string('username is required'),v.minLength(3,'Needs to be at least 3 characters'),v.endsWith('cool','Needs to end with `cool`'),),password:v.string('password is required'),});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:valibotResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/><inputtype="password"{...register('password')}/><inputtype="submit"/></form>);};
Universal adapter for schema validation, compatible withany validation library
import{useForm}from'react-hook-form';import{typeschemaResolver}from'@hookform/resolvers/typeschema';import{z}from'zod';// Use your favorite validation libraryconstschema=z.object({username:z.string().min(1,{message:'Required'}),password:z.number().min(1,{message:'Required'}),});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:typeschemaResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/><inputtype="password"{...register('password')}/><inputtype="submit"/></form>);};
A powerful TypeScript framework that provides a fully-fledged functional effect system with a rich standard library.
importReactfrom'react';import{useForm}from'react-hook-form';import{effectTsResolver}from'@hookform/resolvers/effect-ts';import{Schema}from'effect';constschema=Schema.Struct({username:Schema.String.pipe(Schema.nonEmptyString({message:()=>'username required'}),),password:Schema.String.pipe(Schema.nonEmptyString({message:()=>'password required'}),),});typeFormData=typeofschema.Type;interfaceProps{onSubmit:(data:FormData)=>void;}functionTestComponent({ onSubmit}:Props){const{ register, handleSubmit,formState:{ errors},// provide generic if TS has issues inferring types}=useForm<FormData>({resolver:effectTsResolver(schema),});return(<formonSubmit={handleSubmit(onSubmit)}><input{...register('username')}/>{errors.username&&<spanrole="alert">{errors.username.message}</span>}<input{...register('password')}/>{errors.password&&<spanrole="alert">{errors.password.message}</span>}<buttontype="submit">submit</button></form>);}
VineJS is a form data validation library for Node.js
import{useForm}from'react-hook-form';import{vineResolver}from'@hookform/resolvers/vine';importvinefrom'@vinejs/vine';constschema=vine.compile(vine.object({username:vine.string().minLength(1),password:vine.string().minLength(1),}),);constApp=()=>{const{ register, handleSubmit}=useForm({resolver:vineResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/>{errors.username&&<spanrole="alert">{errors.username.message}</span>}<input{...register('password')}/>{errors.password&&<spanrole="alert">{errors.password.message}</span>}<buttontype="submit">submit</button></form>);};
A TypeScript-first library for building strongly-typed validation rules
import{useForm}from'react-hook-form';import{fluentValidationResolver}from'@hookform/resolvers/fluentvalidation-ts';import{Validator}from'fluentvalidation-ts';classFormDataValidatorextendsValidator<FormData>{constructor(){super();this.ruleFor('username').notEmpty().withMessage('username is a required field');this.ruleFor('password').notEmpty().withMessage('password is a required field');}}constApp=()=>{const{ register, handleSubmit}=useForm({resolver:fluentValidationResolver(newFormDataValidator()),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/>{errors.username&&<spanrole="alert">{errors.username.message}</span>}<input{...register('password')}/>{errors.password&&<spanrole="alert">{errors.password.message}</span>}<buttontype="submit">submit</button></form>);};
A standard interface for TypeScript schema validation libraries
Example zod
import{useForm}from'react-hook-form';import{standardSchemaResolver}from'@hookform/resolvers/standard-schema';import{z}from'zod';constschema=z.object({name:z.string().min(1,{message:'Required'}),age:z.number().min(10),});constApp=()=>{const{ register, handleSubmit,formState:{ errors},}=useForm({resolver:standardSchemaResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('name')}/>{errors.name?.message&&<p>{errors.name?.message}</p>}<inputtype="number"{...register('age',{valueAsNumber:true})}/>{errors.age?.message&&<p>{errors.age?.message}</p>}<inputtype="submit"/></form>);};
Example arkType
import{useForm}from'react-hook-form';import{standardSchemaResolver}from'@hookform/resolvers/standard-schema';import{type}from'arktype';constschema=type({username:'string>1',password:'string>1',});constApp=()=>{const{ register, handleSubmit}=useForm({resolver:standardSchemaResolver(schema),});return(<formonSubmit={handleSubmit((d)=>console.log(d))}><input{...register('username')}/><inputtype="password"{...register('password')}/><inputtype="submit"/></form>);};
Thanks go to all our backers! [Become a backer].
Thanks go to these wonderful people! [Become a contributor].
About
📋 Validation resolvers: Yup, Zod, Superstruct, Joi, Vest, Class Validator, io-ts, Nope, computed-types, typanion, Ajv, TypeBox, ArkType, Valibot, effect-ts, VineJS and Standard Schema