Search code examples
reactjsvalidationreact-hooksrecaptchaemail-validation

React reCaptcha alert on screen instead of error messages


The issue I'm having in my form is that when the reCaptcha verification is successful, the alert message is being shown instead of the error messages for any empty or complete input fields. The console indicates that the reCaptcha is successful but the alert will pop-up whenever the submit button is pressed.

import React, {useState, useRef, Suspense, lazy} from 'react'
import Stockpic from '../../media/stockpic.webp';
import ReCAPTCHA from "react-google-recaptcha";
import axios from 'axios';
import emailjs from 'emailjs-com';
import { useForm } from 'react-hook-form';

const Contact = () => {
  
  const [valid, setValid] = useState(false);
  const form = useRef();
  const [formErrors, setFormErrors] = useState({});

  const submitForm = (e) => {
    e.preventDefault();
    if (!form.current['message'].value.trim()) {
      setFormErrors({ ...formErrors, 'message': "Please enter a message" });
    } 
    if (!form.current['email'].value.trim()) {
      setFormErrors({ ...formErrors, 'email':"Please enter a valid email address"});
    } 
    if (!form.current["first-name"].value.trim()) {
      setFormErrors({ ...formErrors, 'first-name': "Please enter your first name"});
    } 
    if (!form.current["last-name"].value.trim()) {
      setFormErrors({ ...formErrors, 'last-name': "Please enter your last name"});
    } 
    setFormErrors(formErrors);
    if (!valid)
     {
      alert("Please verify you are not a robot")
    } else
    if (Object.keys(formErrors).length === 0) {
      emailjs.sendForm(`${process.env.REACT_APP_SERVICE_ID}`, `${process.env.REACT_APP_TEMPLATE_ID}`, form.current, `${process.env.REACT_APP_PUBLIC_KEY}`)
      form.current.reset();
      alert('Enquiry Sent!')
    }
  }

const captchaRef = useRef(null);

const reCaptchaValue = async () => {
  const token = captchaRef.current.getValue();
  console.log(token);
  await axios
    .post("http://localhost:4000/status", {
      response: token,
    })
    .then((res) => {
      console.log(res);
      setValid(res.data.success);
      if (!res.data) {
        alert("Please verify you are not a robot");
      }
    })
    .catch((err) => {
      console.log(err);
    });
};

  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm({
    mode: "onChange"
  });

const LazyNav = lazy(() => import('../../Components/Navigation.jsx'))
const LazyFooter = lazy(() => import('../../Components/Footer.jsx'))

  return (
  <div>
    <Suspense fallback={<div />}>  
      <LazyNav/>
      </Suspense>
        <div>
          <div>
            Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolorum necessitatibus sunt, officia eveniet distinctio consequatur eius minima perspiciatis vel laborum assumenda magnam esse quae quas. Sint asperiores inventore eveniet iste!
          </div>
          <div>
            <img src={Stockpic} alt="" />
          </div>
            <form ref={form} onSubmit={handleSubmit(submitForm)}>
              <input className='contact-input' type='text' name='first-name' placeholder='Your First Name' required {...register("first-name", { required: true})} />
                {errors['first-name']  && <div className="text-red-600">{formErrors['first-name']}</div>}
              <input className='contact-input' type='text' name='last-name' placeholder='Your Last Name' required {...register("last-name", { required: true})} />
                {errors['last-name'] && <div className="text-red-600">{formErrors['last-name']}</div>}
              <input className='contact-input' type='email' name='email' placeholder='Your Email Address' 
              required {...register("email", {
                  required: true, 
                  pattern: {value: /^\S+@\S+$/i, }
                  })} 
                  />
                  {errors['email'] && <div className="text-red-600">{formErrors['email']}</div>}
              <textarea className='border-black border rounded-md block sm:w-1/2 mobile:w-5/6 tablet:w-full pl-2 resize-none hover:placeholder-gold placeholder:text-center mobile:text-base' name="message" rows="4" placeholder='Message' maxLength="6000" required></textarea>
                {errors['message'] && <div className="text-red-600">{formErrors['last-name']}</div>}
              <ReCAPTCHA 
              sitekey={`${process.env.REACT_APP_SITE_KEY}`}
              ref={captchaRef}
              onChange={() =>
              reCaptchaValue()}
              />
              <button onClick={submitForm} type="submit" href="#_">
                  <span className="relative">SEND</span>
              </button>
          </form>
        </div>
        <Suspense>
      <LazyFooter/>
    </Suspense>
  </div>
  )

  export default Contact


Solution

  • This should be an issue with updating valid state with res.data.success
    If res.data.success is undefined or null then if (!valid) will always return true so the alert will pop-up anyway.
    You should set valid to true based on condition, because in your example if there is a response valid will be updated whatever the response is, so what you have to do is something like this :

    .then((res) => {
       if (condition_that_makes_valid_true) {
         setValid(true);
       }else {
         alert("Please verify you are not a robot");
         setValid(false);
       }
    })