Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting "Cannot read properties of null (reading useRef)" Only When Using ReCAPTCHA Component #285

Open
saidkharboutli opened this issue Feb 6, 2024 · 1 comment

Comments

@saidkharboutli
Copy link

react-google-recaptcha version: 3.1.0
react-async-script version: 1.2.0


Hello! I've been trying to get this working since yesterday and I am left scratching my head as to what could possibly be happening. For context, building a React + Astro website.

Firstly, my module which is using the ReCAPTCHA component:

import emailjs from '@emailjs/browser';
import React, { useEffect } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';

import { Section } from '../Section';

const AboutMeContact = () => {
  const form = React.useRef<HTMLFormElement>();
  const recaptchaRef = React.useRef<ReCAPTCHA>();

  const [showPopup, setShowPopup] = React.useState(false);
  const [animateContents, setAnimateContents] = React.useState(false);
  const [sending, setSending] = React.useState(false);

  useEffect(() => {
    setTimeout(() => {
      setAnimateContents(showPopup);
    }, 10);
  }, [showPopup]);

  const handleSubmit = (e: React.FormEvent) => {
    const serviceId = 'contact-saidk';
    const templateId = 'template_4akaltp';
    const publicKey = 'PPTQzYEGERUyGNf3B';

    e.preventDefault();

    const recaptcha = recaptchaRef.current.executeAsync();
    setSending(true);
    emailjs.sendForm(serviceId, templateId, form.current, publicKey).then(
      () => {
        form.current.reset();
        setShowPopup(true);
        setTimeout(() => setShowPopup(false), 2000);
        setTimeout(() => {
          setAnimateContents(false);
          setSending(false);
        }, 1800);
      },
      (error) => {
        setSending(false);
        console.log(error.text);
      },
    );
  };

  return (
    <Section>
      <div className="flex w-full justify-center">
        <form
          onSubmit={handleSubmit}
          ref={form}
          className="flex flex-col gap-6 md:w-2/3"
        >
          <ReCAPTCHA
            ref={recaptchaRef}
            size="invisible"
            sitekey="-asdagdaege123123"
          />
          <div className="flex flex-col gap-2 md:flex-row md:justify-between md:gap-8">
            <div className="w-full">
              <label className="mb-2 font-semibold">Name</label>
              <input
                type="text"
                name="from_name"
                className="w-full rounded-md border border-gray-300 bg-cod-900 px-4 py-2 focus:bg-cod-800"
                required
              />
            </div>
            <div className="w-full">
              <label htmlFor="email" className="mb-2 font-semibold">
                Email
              </label>
              <input
                type="email"
                name="user_email"
                className="w-full rounded-md border border-gray-300 bg-cod-900 px-4 py-2 focus:bg-cod-800"
                required
              />
            </div>
          </div>
          <div className="">
            <label className="mb-2 font-semibold">Message</label>
            <textarea
              name="message"
              className="w-full rounded-md border border-gray-300 bg-cod-900 px-4 py-2 focus:bg-cod-800"
              required
            />
          </div>
          <div className="invisible" id="g-recaptcha-response"></div>
          <button
            type="submit"
            id="submit-button"
            className="self-center rounded-md bg-[#BB86FC] px-4 py-2 text-cod-950 transition-all duration-200 hover:scale-110"
          >
            {sending ? 'Sending...' : 'Submit'}
          </button>
        </form>
        {showPopup && (
          <div
            className={`fixed left-0 top-0 flex size-full items-center justify-center bg-black ${animateContents ? 'opacity-75' : 'opacity-0'} transition-opacity duration-100`}
            onClick={() => {
              setShowPopup(false);
              setSending(false);
            }}
          >
            <div
              className={`rounded bg-cod-800 p-4 text-center transition-all duration-200 ${animateContents ? 'translate-y-0' : '-translate-y-4'} `}
            >
              <h2 className="mb-2 text-2xl">
                <GradientText>Success!</GradientText>
              </h2>
              <p>
                Successfully submitted. <br />
                I'll get back to you as soon as possible!
              </p>
            </div>
          </div>
        )}
      </div>
    </Section>
  );
};

export { AboutMeContact };

If I remove the ReCAPTCHA component from my form component, it works. If I add it back in, it throws this error. The useRef it references is the very first one of the script (even if I remove useRef completely, it starts having problems with useState, so seems like these functions are being overrode by something).

One other thing to note, I get the following error in the console pointing to the line I load the component in my form:

Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

My understanding is that this error is caused by importing a default export with braces (or vice versa). I am not doing that, and I am following the guide's method for importing.

Any thoughts/help is appreciated. I can provide any further context possibly necessary.

@SychevAndrey
Copy link

@saidkharboutli For AboutMeContact component use client:only astro attribute, it should help.
<AboutMeContact client:only />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants