React hook form を使う @yukilulu0229

https://react-hook-form.com/

## install

```
npm install react-hook-form
```

https://react-hook-form.com/get-started

## 簡易な解説

```app.tsx
"use client";
import { useRouter } from "next/navigation";
// use client と書くとクライアントレンダリングになる,react hooks formがクライアントでしかつかえないため
import React from "react";
import { useForm, SubmitHandler } from "react-hook-form";
import { createUserWithEmailAndPassword, UserCredential } from "@firebase/auth";
import { auth } from "../../../../firebase";

type Inputs = {
  email: string;
  password: string;
};

const Register = () => {
  const router = useRouter();

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<Inputs>();

  const onSubmit: SubmitHandler<Inputs> = async (data) => {
    await createUserWithEmailAndPassword(auth, data.email, data.password)
      .then((userCredential: UserCredential) => {
        const user = userCredential.user;
        router.push("/auth/login");
      })
      .catch((error) => {
        if (error.code === "auth/email-already-in-use") {
          alert("このメールアドレスはすでに使用されています");
        } else {
          alert(error.message);
        }
      });
  };
  return (
    <div className="h-screen flex flex-col items-center justify-center">
      <form
        onSubmit={handleSubmit(onSubmit)}
        className="bg-white p-8 rounded-lg shadow-md w-96"
      >
        <h1 className="mb-4 text-2xl text-gray-700 font-medium">新規登録</h1>

        <div className="mb-4">
          <label className="block text-sm font-medium text-gray-600" htmlFor="">
            Email
          </label>
          <input
            {...register("email", {
              // required: true,
              required: "メールアドレスは必須です", // 直接エラーの文章を書くことができる
              pattern: {
                value:
                  /^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/,
                message: "不適切なアドレスです",
              },
            })}
            className="mt-1 border-2 rounded-md w-full p-2"
            type="email"
          />
          {errors.email && (
            <span className="text-red-600 text-sm">{errors.email.message}</span>
          )}
        </div>

        <div className="mb-4">
          <label className="block text-sm font-medium text-gray-600" htmlFor="">
            Password
          </label>
          <input
            className="mt-1 border-2 rounded-md w-full p-2"
            type="password"
            {...register("password", {
              // required: true,
              required: "パスワードは必須です", // 直接エラーの文章を書くことができる
              minLength: {
                value: 6,
                message: "6文字以上入力してください",
              },
              maxLength: {
                value: 30,
                message: "30文字以内で入力してください",
              },
            })}
          />
          {errors.password && (
            <span className="text-red-600 text-sm">
              {errors.password.message}
            </span>
          )}
        </div>

        <div className="flex justify-end">
          <button
            className="bg-blue-500 text-white font-bold py-2 px-4 rounded hover:bg-blue-700"
            type="submit"
          >
            新規登録
          </button>
        </div>

        <div className="mt-4">
          <span className="text-gray-600 text-sm">
            すでにアカウントをお持ちですか
          </span>
          <button className="text-blue-500 text-sm font-bold ml-1 hover:text-blue-700">
            ログインページへ
          </button>
        </div>
      </form>
    </div>
  );
};

export default Register;

```

```
"use client";
```
Nextだとサーバーサイドレンダリングになるのでクライアント側とわからせる必要がる

```
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<Inputs>();
```

Inputsでフォームの中身に入ってくるものの型を決める

```
<form
    onSubmit={handleSubmit(onSubmit)}
    className="bg-white p-8 rounded-lg shadow-md w-96"
>
```

submitしたときにエラーを拾うようにする

```
<input
    {...register("email", {
      required: "メールアドレスは必須です", // 直接エラーの文章を書くことができる
      pattern: {
        value:
          /^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/,
        message: "不適切なアドレスです",
      },
    })}
/>
```

- emailという名前付け
- 必須やバリデーションやメッセージ

```
{errors.email && (
    <span className="text-red-600 text-sm">{errors.email.message}</span>
)}
```

エラーメッセージを出す