🍣

ReacthookformとYup

2023/10/27に公開

reactでform画面を作成しようとしたところ、ReactHookFormとYupというバリデーションする際に便利なライブラリがあるということで今回記事にしました。

パッケージのインストール

パッケージ管理ツールはpnpmを使用してます。

  1. React-hook-formのインストール
$ pnpm install react-hook-form
  1. @hookform/resolversのインストール
$ pnpm install @hookform/resolvers
  1. Yupのインストール
$ pnpm install yup

useStateを使用した画面の作成

'use client'
import { Button } from '@nextui-org/react';
import React, { useState } from 'react';

function SimpleForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [emailError, setEmailError] = useState('');
  const [passwordError, setPasswordError] = useState('');

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();

    if (email === '') {
      setEmailError('メールアドレスを入力してください');
    } else {
      setEmailError('');
    }

    if (password === '') {
      setPasswordError('パスワードを入力してください');
    } else {
      setPasswordError(''); 
    }

    if (email !== '' && password !== '') {
      console.log('Email: ', email);
      console.log('Password: ', password);
    }
  };

  return (
    <div className="flex items-center justify-center">
      <form className='mt-8 flex flex-col' onSubmit={handleSubmit}>
        <h1 className="text-2xl">ログイン</h1>
        <div className="mb-4">
          <input
            type="email"
            value={email}
            placeholder="Email"
            onChange={(e) => setEmail(e.target.value)}
            className='mb-2 w-full rounded border border-gray-300 px-2 py-4'
          />
          {emailError && (
            <p className='text-sm text-red-500'>{emailError}</p>
          )}
        </div>
        <div className="mb-6">
          <input
            type="password"
            value={password}
            placeholder="Password"
            onChange={(e) => setPassword(e.target.value)}
            className='mb-2 w-full rounded border border-gray-300 px-2 py-4'
          />
          {passwordError && (
            <p className='text-sm text-red-500'>{passwordError}</p>
          )}
        </div>
        <Button type="submit" className='my-8 bg-blue-500 text-center text-white'>
          ログイン
        </Button>
      </form>
    </div>
  );
}

export default SimpleForm;



こちらはusestateを使って、作成したemailとpasswordが入力されてないとエラーメッセージを出す簡単なform画面です。
こちらをReacthookformとyupを使用したものに書き換えます。

ReactHookFormとYupを使用した画面作成

'use client'

'use client'

import { yupResolver } from '@hookform/resolvers/yup';
import { Button } from '@nextui-org/react';
import React, { useState } from 'react';
import { useForm } from 'react-hook-form';
import * as yup from 'yup'

interface FormData {
  email:string
  password:string
}

const schema = yup.object().shape({
  email: yup.string()
  .required('メールアドレスを入力してください')
  .email('メールアドレスを入力してください'),
  password: yup.string().required('パスワードを入力してください'),
})

const SimpleForm = () => {
  type FormData = yup.InferType<typeof schema>

  const {
    handleSubmit,
    register,
    formState: { errors },
    reset,
  } = useForm<FormData>({
    mode: 'onSubmit',
    resolver: yupResolver(schema),
  })

  const onSubmit = (data: FormData) => {
    reset()
  }

  return (
    <div className="flex items-center justify-center">
      <form className='mt-8 flex flex-col' onSubmit={handleSubmit(onSubmit, (e) => {console.error(e)})}>
        <h1 className="text-2xl">ログイン</h1>
        <div className="mb-4">
          <input
            type="email"
            placeholder="Email"
            className='mb-2 w-full rounded border border-gray-300 px-2 py-4'
            {...register('email')}
          />
          {errors.email && (
            <p className='text-sm text-red-500'>{errors.email.message}</p>
          )}
        </div>
        <div className="mb-6">
          <input
            type="password"
            placeholder="Password"
            className='mb-2 w-full rounded border border-gray-300 px-2 py-4'
            {...register('password')}
          />
          {errors.password && (
            <p className='text-sm text-red-500'>{errors.password.message}</p>
          )}
        </div>
        <Button type="submit" className='my-8 bg-blue-500 text-center text-white'>
          ログイン
        </Button>
      </form>
    </div>
  );
}

export default SimpleForm;
  const schema = yup.object().shape({
    email: yup.string().required('メールアドレスを入力してください'),
    password: yup.string().required('パスワードを入力してください')
  })
  type FormData = yup.InferType<typeof schema>

ここではYupを使用してフォームのバリデーションスキーマを設定しています。
emailとpasswordに対するエラーのバリデーションルールを指定しています。

  const {
    handleSubmit,
    register,
    formState: { errors },
    reset,
  } = useForm<FormData>({
    mode: 'onSubmit',
    resolver: yupResolver(schema),
  })

このコードは、Reactアプリケーション内でフォームを制御し、バリデーションを行うために react-hook-form と yup を統合して使用しています。
useForm はフォームの制御を提供し、 mode: 'onSubmit' と resolver: yupResolver(schema) を設定することで送信時にバリデーションがトリガーされます。 handleSubmit 関数はフォームの送信時にバリデーションが実行され、 register はフォームフィールドの登録を行います。

registerと似たようなことをcontrollerでもできるみたいで何が違うのか調べたら下記サイトで解説してくれていました。
https://scrapbox.io/mrsekut-p/react-hook-formでregisterとControllerのどちらを使うか

Discussion