Closed8
NextJSで、react-hook-formのフォームにreCAPTCHA V2を導入する
Yup × react-hook-formで実装しているフォームにreCAPTCHAを導入したい
前提として、以下を想定している
- フロント側でreCAPTCHAの認証を行い、tokenを保存する
- Submit時にtokenをバックエンドに送る
- バックエンドでトークンを検証する
- 問題があればBad Requestを返す
- 問題がなければ保存する
Submitまでを検証する
まずはNextJSのプロジェクトを作成して、簡単なフォームを作成する
terminal
$ pnpm create next-app
✔ What is your project named? … test
✔ Would you like to use TypeScript? … Yes
✔ Would you like to use ESLint? … Yes
✔ Would you like to use Tailwind CSS? … Yes
✔ Would you like to use `src/` directory? … Yes
✔ Would you like to use App Router? (recommended) … Yes
✔ Would you like to customize the default import alias (@/*)? … Yes
✔ What import alias would you like configured? … @/*
terminal
$ pnpm add yup react-hook-form @hookform/resolvers
terminal
pnpm dev
=> open localhost:3000
react-hook-formの例を参考にフォームを追加する
page.tsx
'use client'
import { useForm } from "react-hook-form"
import { yupResolver } from "@hookform/resolvers/yup"
import * as yup from "yup"
import { NextPage } from "next"
const schema = yup
.object({
firstName: yup.string().required(),
age: yup.number().positive().integer().required(),
})
.required()
const Page: NextPage = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(schema),
})
const onSubmit = (data) => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<p>firstName</p>
<input {...register("firstName")} />
<p style={{color: 'red'}}>{errors.firstName?.message}</p>
<p>age</p>
<input {...register("age")} />
<p style={{color: 'red'}}>{errors.age?.message}</p>
<input type="submit" />
</form>
)
}
export default Page
参考
reCAPTCHAのセットアップ
また、保存の先のページのサイトキー、シークレットキーを控えておく
参考
reCAPTCHAを表示するライブラリを入れる
terminal
$ pnpm add react-google-recaptcha
以下が基本実装
reCAPTCHAのセットアップで取得したsitekeyをいれる
チェックを完了したら、onChangeが発火するようです。
page.tsx
'use client'
import ReCAPTCHA from "react-google-recaptcha";
const onChange = (value: string) => {
console.log("Captcha value:", value);
}
---
<ReCAPTCHA
sitekey="your site key"
onChange={onChange}
/>
ここまででフォームにreCAPTCHAのComponentが表示される
$ pnpm dev
=> https://localhost:3000
page.tsx
const onChange = (value: string) => {
console.log("Captcha value:", value);
}
チェックボタンを通すことで
上記の実装部分のvalueにトークンが返ることを確認できる
react-hook-formにreCAPTCHAのトークンを載せる
onChangeの発火時にreact-hook-formに載せようと思う。
setValueを使ってreCAPTCHA用のkeyにセットします。
実装
以下の実装で、token
のkeyに保存することができた
schema
token: yup.string().required()
page.tsx(schema)
const schema = yup
.object({
firstName: yup.string().required(),
age: yup.number().positive().integer().required(),
token: yup.string().required()
})
.required()
onChange
setValue("token", value);
page.tsx(onChange)
const onChange = (value: string) => {
setValue("token", value);
console.log("Captcha value:", value);
}
参考
チェックできていないとエラーが出ることを確認した
また、タイムアウトでチェックが外れたときもrequiredでエラーになることが確認できた
実装のすべて
page.tsx
'use client'
import { useForm } from "react-hook-form"
import { yupResolver } from "@hookform/resolvers/yup"
import * as yup from "yup"
import { NextPage } from "next"
import ReCAPTCHA from "react-google-recaptcha";
const schema = yup
.object({
firstName: yup.string().required(),
age: yup.number().positive().integer().required(),
token: yup.string().required()
})
.required()
const Page: NextPage = () => {
const {
register,
handleSubmit,
formState: { errors },
setValue
} = useForm({
resolver: yupResolver(schema),
})
const onChange = (value: string) => {
setValue("token", value);
console.log("Captcha value:", value);
}
const onSubmit = (data) => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<p>firstName</p>
<input {...register("firstName")} />
<p style={{color: 'red'}}>{errors.firstName?.message}</p>
<p>age</p>
<input {...register("age")} />
<p style={{color: 'red'}}>{errors.age?.message}</p>
<ReCAPTCHA
sitekey="your site key"
onChange={onChange}
/>
<p style={{color: 'red'}}>{errors.token?.message}</p>
<input type="submit" />
</form>
)
}
export default Page
このスクラップは2024/05/05にクローズされました