This content originally appeared on DEV Community and was authored by Zach Koch
Using useFormState and useActionState
Next.js documentation currently encourages the use of useFormState
and useActionState
to submit form data to your server actions.
I will show you how I got Google's reCaptcha v3 working with useFormState
. This may also apply to useActionState
, but I have not tested it.
Setting up reCAPTCHA
Go to the reCAPTCHA v3 admin console and create a new site if you don't have one yet
Your configuration should have
- A label for your project
- Score Based (v3) selected
-
localhost
andyour site url
both added as domains
After submitting the next page will let you copy the keys that you will need to add to your project in the next section
Setting up environment variables
In your project create a file called .env.local
if you don't have one
In this file add your keys
.env.local
NEXT_PUBLIC_RECAPTCHA_SITE_KEY=yoursitekeygoeshere
RECAPTCHA_SECRET_KEY=yoursecretkeygoeshere
Make sure you have this file added to .gitignore
adding
NEXT_PUBLIC_
to our variable allows it to be accessed in the browser
react-google-recaptcha-v3
install react-google-recaptcha-v3
npm i -S react-google-recaptcha-v3
This package comes with GoogleReCaptchaProvider
, a component that runs the reCaptcha script that detects bots and provides the result to any child components.
The documentation states that it should places as high as possible in the tree, but I found that I would get errors if it was outside the bounds of a client component.
In my case I wrapped it in the same file as my form component
Contact.tsx
'use client';
import {
GoogleReCaptchaProvider, useGoogleReCaptcha
} from 'react-google-recaptcha-v3';
export default function Contact() {
return (
<GoogleReCaptchaProvider
reCaptchaKey={
process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY ?? ''
}>
<ContactForm />
</GoogleReCaptchaProvider>
)
}
function ContactForm() {
// my form component
}
Integrate with useFormState
Normally we would set up useFormState
by providing it with a server action that handles our form data.
In this case we want to add the reCAPTCHA data just before submitting to the server.
To do this we will
- make a function with that accepts
prevState
andformData
- get our captcha response from the reCAPTCHA script using executeRecaptcha
- attach the captcha response to our form as a form field
- send it off to our server action
Contact.tsx
just inside your form component
const initialState: MessageState = { message: null, errors: {}};
const [state, formAction] = useFormState(addRecaptcha, initialState);
const { executeRecaptcha } = useGoogleReCaptcha();
async function addRecaptcha(prevState: MessageState, formData: FormData) {
let gRecaptchaToken = ''
if (executeRecaptcha) {
gRecaptchaToken = await executeRecaptcha('contactMessage');
}
formData.set('captcha', gRecaptchaToken);
return createMessage(prevState, formData)
}
The form action will go at the top of your form
Contact.tsx
<form action={formAction}>
// your form
</form>
When you submit, the token that is created by the captcha provider will be sent to your server action as just another field
Validating captcha data
In your server action you will recieve your captcha token as part of your form data.
You can send the token to Google to verify
If the verification fails you can treat it the same way you would treat validation for any failed field in your form.
Contact.tsx
async function validateCaptcha(captchaToken: string) {
const secretKey = process.env.RECAPTCHA_SECRET_KEY;
const captchaResponse = await fetch(
`https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${captchaToken}`, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" }
});
const res = await captchaResponse.json();
return res.score;
}
const score = await validateCaptcha(formData.get('captcha') ?? '')
Hopefully that is enough to help you integrate captcha. I'll update this for useActionState
in the future. I am currently using this on my own site. Let me know in the comments if you spot any issues or if anything is unclear.
This content originally appeared on DEV Community and was authored by Zach Koch
Zach Koch | Sciencx (2024-09-04T20:45:35+00:00) Using reCAPTCHA v3 with Next.js 14. Retrieved from https://www.scien.cx/2024/09/04/using-recaptcha-v3-with-next-js-14/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.