---
# System prepended metadata

title: React hook form + yup + typescript
tags: [validate, yup, react hook form, typescript]

---

# React hook form + yup + typescript

==note: xem các file `Register.tsx` và `utils/rules.ts` của `Ecommerce`==
## CÁCH 1 : React hook form 
```javascript
yarn add react-hook-form
```

**1. Component input**
```javascript
import type { UseFormRegister, RegisterOptions } from 'react-hook-form'
interface Props {
  type: React.HTMLInputTypeAttribute
  errorMessage?: string
  placeholder?: string
  className?: string
  name: string
  register: UseFormRegister<any>
  rules?: any
}
const CustomInput = ({ type, errorMessage, placeholder, className, name, register, rules }: Props) => {
  return (
    <div className={className}>
      <input
        type={type}
        {...register(name, rules)}
        placeholder={placeholder}
        className=""
      />
      <div className='text-red-500 text-[13px] min-h-[28px]'>{errorMessage}</div>
    </div>
  )
}

export default CustomInput

```

**2. Use in component**
```javascript
interface FormData {
  email: string
  password: string
  confirmPassword: string
}

const Register = () => {
  const {
    register,
    handleSubmit,
    watch,
    getValues,
    formState: { errors }
  } = useForm<FormData>()
  const rules = getRules(getValues)
  const onSubmit = handleSubmit(
    (data) => {
      console.log(data)
    },
    (data) => {
      const password = getValues('password')

      console.log(password)
    }
  )
  
  return (  <CustomInput
          type='email'
          placeholder='Email'
          name='email'
          register={register}
          className=''
          errorMessage={errors.email?.message}
          rules={rules.email}
        />)
```
**3. File `rules.ts` sử dụng getValues() để validate**
```javascript=
export const getRules = (getValues: any) => ({
  email: {
    required: {
      value: true,
      message: 'Vui lòng nhập email'
    },
    pattern: {
      value: /^\S+@\S+\.\S+$/,
      message: 'Email không đúng định dạng'
    },
    maxLength: {
      value: 30,
      message: 'Email không được dài hơn 30 ký tự'
    },
    minLength: {
      value: 5,
      message: 'Email không được ngắn 5 ký tự'
    }
  },
  password: {
    required: {
      value: true,
      message: 'Vui lòng nhập mật khẩu'
    },
    maxLength: {
      value: 30,
      message: 'Mật khẩu không được dài hơn 30 ký tự'
    },
    minLength: {
      value: 5,
      message: 'Mật khẩu không được ngắn 5 ký tự'
    }
  },
  confirmPassword: {
    required: {
      value: true,
      message: 'Vui lòng xác thực mật khẩu'
    },
    maxLength: {
      value: 30,
      message: 'Xác thực mật khẩu không được dài hơn 30 ký tự'
    },
    minLength: {
      value: 5,
      message: 'Xác thực mật khẩu không được ngắn 5 ký tự'
    },
    validate:
      typeof getValues === 'function'
        ? (value:any) => value === getValues('password') || 'Xác thực mật khẩu không giống'
        : undefined
  }
})
```

## CÁCH 2:  NÊN DÙNG react-hook-form + yup
**Install package**
```javascript
npm install @hookform/resolvers yup

yarn add @hookform/resolvers yup
```

**1. File `rule.ts`**
```javascript
export const schema = yup.object({
  email: yup
    .string()
    .required('Vui lòng nhập email')
    .email('Email không đúng định dạng')
    .min(5, 'Email có ít nhất 5 ký tự')
    .max(50, 'Email không thể dài hơn 50 ký tự'),
  password: yup
    .string()
    .required('Vui lòng nhập mật khẩu')
    .min(5, 'Mật khẩu có ít nhất 5 ký tự')
    .max(50, 'Mật khẩu không thể dài hơn 50 ký tự'),
  confirmPassword: yup
    .string()
    .required('Vui lòng nhập xác thực mật khẩu')
    .min(5, 'Xác thực mật khẩu có ít nhất 5 ký tự')
    .max(50, 'Xác thực mật khẩu không thể dài hơn 50 ký tự')
    .oneOf([yup.ref('password')], 'Xác thực mật khẩu không giống')
})

export const loginSchema = schema.omit(['confirmPassword']); // omit là loại bỏ 

export type Schema = yup.InferType<typeof schema>
export type LoginSchema = yup.InferType<typeof loginSchema>
```
**2. CustomInput**
```javascipt
import type { UseFormRegister, RegisterOptions } from 'react-hook-form'
interface Props {
  type: React.HTMLInputTypeAttribute
  errorMessage?: string
  placeholder?: string
  className?: string
  name: string
  register: UseFormRegister<any>
  rules?: any
  autoComplete?: string | undefined
}
const CustomInput = ({ type, errorMessage, placeholder, className, name, register, rules ,autoComplete}: Props) => {
  return (
    <div className={className}>
      <input
        type={type}
        {...register(name, rules)}
        placeholder={placeholder}
        autoComplete={autoComplete}
        className='w-full dark:text-white border rounded-md p-3 dark:bg-third-dark outline-none dark:border-primary-dark'
      />
      <div className='text-red-500 text-[13px] min-h-[28px]'>{errorMessage}</div>
    </div>
  )
}

export default CustomInput
```

**3. Component login**
```javascript
import { loginSchema, LoginSchema } from 'src/utils/rule'
import { yupResolver } from '@hookform/resolvers/yup'

const Login = () => {
  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm<LoginSchema>({
    resolver: yupResolver(loginSchema)
  })

  const onSubmit = handleSubmit(
    (data) => {
      console.log(data)
    }
  )
  return (
      <form noValidate onSubmit={onSubmit}>
        <CustomInput
          type='email'
          placeholder='Email'
          name='email'
          register={register}
          className=''
          errorMessage={errors.email?.message}
        />
        <CustomInput
          type='password'
          placeholder='Mật khẩu'
          name='password'
          register={register}
          className=''
          errorMessage={errors.password?.message}
        />

        <PrimaryButton type='submit' content='Đăng nhập' className='w-full mt-2' />
```