フォームガード

1import Link from 'next/link';
2import React from 'react';
3import { useForm } from 'react-hook-form';
4import { HiBan, HiOutlineCheck } from 'react-icons/hi';
5import { useFormGuard } from '../lib/form-guard';
6
7const FormGuard = () => {
8  const {
9    register,
10    handleSubmit,
11    reset,
12    formState: { isDirty },
13  } = useForm();
14
15  useFormGuard(isDirty);
16
17  const submit = () => {
18    alert('送信したので確認なく遷移できるようになります。');
19    reset(undefined, {
20      keepValues: true,
21    });
22  };
23
24  return (
25    <div>
26      <form onSubmit={handleSubmit(submit)}>
27        <div className="flex items-center space-x-4 mb-4">
28          <input
29            className="rounded-full bg-transparent"
30            type="text"
31            {...register('name')}
32            autoComplete="off"
33          />
34          <button className="">送信</button>
35        </div>
36      </form>
37      <p className="flex items-center space-x-2">
38        {isDirty ? (
39          <>
40            <HiBan className="text-red-500" />
41            <span>確認なく離脱できません</span>
42          </>
43        ) : (
44          <>
45            <HiOutlineCheck className="text-lime-500" />
46            <span>確認なく離脱できます</span>
47          </>
48        )}
49      </p>
50
51      <hr className="my-6" />
52
53      <p className="mt-6 mb-2 text-sm">次のアクションを実行</p>
54      <div className="space-x-6 flex">
55        <Link href="/">
56          <a className="">別のページへ離脱</a>
57        </Link>
58        <p className="opacity-40">ページをリロード</p>
59        <p className="opacity-40">タブを閉じる</p>
60      </div>
61    </div>
62  );
63};
64
65export default FormGuard;

使用ライブラリ

参考サイト