4

I am trying to implement Google Recaptcha on my contact form in Next.js. It does popup the challenge when needed, but sends the form anyway. Here's my code so far:

  // Recaptcha
  const recaptchaRef = useRef();

  // Form validation
  const [validated, setValidated] = useState(false);

  // Reset form
  const formRef = useRef();
  const handleReset = () => {
    formRef.current.reset();
    setValidated(false);
  };

  // Thank you Message
  const [thankYouMessage, setThankYouMessage] = useState(false);

  // Form submit handler
  async function handleSubmit(e) {
    e.preventDefault();
    e.stopPropagation();

    // Execute the reCAPTCHA when the form is submitted
    recaptchaRef.current.execute();

    const formData = new FormData();

    Array.from(e.currentTarget.elements).forEach((field) => {
      if (!field.name) return;
      formData.append(field.name, field.value);
    });

    await fetch(process.env.NEXT_PUBLIC_WORDPRESS_CF7_ENDPOINT, {
      body: formData,
      method: "POST",
    })
      .then((response) => response.json())
      .then((response) => {
        if (response.status === "mail_sent") {
          setThankYouMessage(!thankYouMessage);
        } else if (response.status === "mail_failed") {
          alert("Message failed to send.");
        }
      });

    setValidated(true);
    handleReset();
    recaptchaRef.current.reset();
  }

And on the form:

  <Form
    ref={formRef}
    validated={validated}
    onSubmit={handleSubmit}
  >
    <ReCAPTCHA
      ref={recaptchaRef}
      size="invisible"
      sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}
    />

This of course does not work because it sends the form anyway even if the recaptcha gets triggered.

I've tried adding onChange={onReCAPTCHAChange} on <ReCAPTCHA /> but then get an error Uncaught (in promise) ReferenceError:

  const onReCAPTCHAChange = (captchaCode) => {
    // If the reCAPTCHA code is null or undefined indicating that
    // the reCAPTCHA was expired then return early
    if (!captchaCode) {
      return;
    }
    // Else reCAPTCHA was executed successfully so proceed with the
    // alert
    alert(`Hey, ${email}`);
    // Reset the reCAPTCHA so that it can be executed again if user
    // submits another email.
    recaptchaRef.current.reset();
  };
Mark
  • 731
  • 2
  • 10
  • 29
  • Try moving whatever needs to happen after the reCAPTCHA check to the `onReCAPTCHAChange` function. – juliomalves Jul 12 '21 at 15:29
  • Ah I guess I understand. What you mean by that is to put `handleSubmit` actions inside the `onReCAPTCHAChange` function right? – Mark Jul 15 '21 at 04:24
  • Yes, that's what I mean. – juliomalves Jul 15 '21 at 06:42
  • @juliomalves I've tried putting everything from `async function handleSubmit(e)` inside `onReCAPTCHAChange` but then the `handleSubmit` function won't work. Care for writing me an example maybe? – Mark Jul 24 '21 at 19:55

1 Answers1

0

I think in your handleSubmit you can use executeAsync method like this (as shown in official documentation), this way you should be able to write everything in handleSubmit:

import ReCAPTCHA from "react-google-recaptcha";
 
 
const ReCAPTCHAForm = (props) => {
  const recaptchaRef = React.useRef();
 
  const handleSubmit = async () => {
    try {
       const token = await recaptchaRef.current.executeAsync();
       // Add your API call code here also pass token to API
    } catch(error) {
      // handle validation error
    }
 
    
  }
 
  return (
    <form onSubmit={handleSubmit}>
      <ReCAPTCHA
        ref={recaptchaRef}
        size="invisible"
        sitekey="Your client site key"
      />
    </form>
  )
 
}
 
ReactDOM.render(
  <ReCAPTCHAForm />,
  document.body
);
Aks
  • 8,181
  • 5
  • 37
  • 38
  • Hello thanks for your answer. Sadly I do not get this `// Add your API call code here also pass token to API` where do I pass the `token` to? – Mark Aug 07 '21 at 23:57
  • ask the project's API developer about it, recaptcha token need to to be verified on backend otherwise it won't add any real security. – Aks Aug 09 '21 at 10:45
  • Oooh I see now so I'd have to pass that token into the API. I am using WordPress Contact Form 7 as the API. It does let me add a recaptcha option. Going to have to figure out what that endpoint will be. – Mark Aug 09 '21 at 15:48