react-google-recaptcha "ref" type error in React typescript

8.3k views Asked by At

I'm trying to implement invisible reCaptcha from react-google-recaptcha in type script project

I added the package's type by

yarn add @types/react-google-recaptcha

but when I want to implement the component, I get a type script error in here

  <ReCAPTCHA
        ref={recaptchaRef} // IN HERE
        size="invisible"
        sitekey="Your client site key"
      />

and this is the error's content

 Type 'MutableRefObject<undefined>' is not assignable to type 'LegacyRef<ReCAPTCHA> | undefined'.''
 Type 'MutableRefObject<undefined>' is not assignable to type 'RefObject<ReCAPTCHA>'.
 Types of property 'current' are incompatible.
2

There are 2 answers

2
Ajeet Shah On BEST ANSWER

Just give it an initial value of null. It takes undefined as initial value in your current implementation.

const recaptchaRef = useRef(null)
// or
const recaptchaRef = useRef<ReCAPTCHA>(null);

// ....

<ReCAPTCHA
  ref={recaptchaRef}
  size="invisible"
  sitekey="Your client site key"
/>

Explanation:

By looking at types, ref attribute expects a type as below:

(JSX attribute) React.ClassAttributes<ReCAPTCHA>.ref?: string | ((instance: ReCAPTCHA | null) => void) | React.RefObject<ReCAPTCHA> | null | undefined

i.e.

string | ((instance: ReCAPTCHA | null) => void) | React.RefObject<ReCAPTCHA> | null | undefined

where RefObject is:

interface RefObject<T> {
  readonly current: T | null;
}

So, the value of current should be of some type or null.

0
Laiacy On

Based on their documentation: Invisible reCAPTCHA You just need to correctly type the recaptcha Ref to avoid a possible Typescript error.

Always that you don't use the executeAsync method you can use React.createRef (since React 16.3) and type your recaptcha ref this way:

import ReCAPTCHA from "react-google-recaptcha";

const recaptchaRef = React.createRef<ReCAPTCHA>()
 
ReactDOM.render(
  <form onSubmit={() => { recaptchaRef.current.execute(); }}>
    <ReCAPTCHA
      ref={recaptchaRef}
      size="invisible"
      sitekey="Your client site key"
      onChange={onChange}
    />
  </form>,
  document.body
);

Additionally, you can use the executeAsync method to use a promise based approach. Then you can avoid the Typescript error this way:

import ReCAPTCHA from "react-google-recaptcha";
 
 
const ReCAPTCHAForm = (props) => {
  const recaptchaRef = React.useRef<ReCAPTCHA>();
 
  const onSubmitWithReCAPTCHA = async () => {
    const token = await recaptchaRef?.current?.executeAsync();
 
    // apply to form data
  }
 
  return (
    <form onSubmit={onSubmitWithReCAPTCHA}>
      <ReCAPTCHA
        ref={recaptchaRef as React.RefObject<ReCAPTCHA>}
        size="invisible"
        sitekey="Your client site key"
      />
    </form>
  )
 
}