5

When loginBefore function is invoked by another component I need to assign the returned captcha token to captchaToken variable but executeRecaptcha is always undefined, so it executes the code block in if statement. Somehow I need to wait until executeRecaptcha function is initialized and then call function of getCaptchaToken I think. Is there any good way to do this? Thanks for the helps.

import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';
export const useAxiosClient = () => {
  const navigate = useNavigate();
  const { executeRecaptcha } = useGoogleReCaptcha();

  const getCaptchaToken = async (action: string) => {
    if (!executeRecaptcha) {
      console.log('Execute recaptcha not yet available');
      return;
    }
    return await executeRecaptcha(action);
  };

  const loginBefore = async () => {
    const captchaToken = await getCaptchaToken('login');

I tried to invoke getCaptchaToken function after a certain amount of delay and that worked but that won't always work and not a good solution I think.

3 Answers 3

0

I used react-google-recaptcha-v3 and that behaviour was very confusing to me. There is a new library that implements invisible reCAPTCHA for react called @rusted/react-recaptcha-v3

It has built-in action queue system that cares about that. Just use as following.

import {
    useExecuteReCaptcha,
    useSkipInjectionDelay,
} from '@rusted/react-recaptcha-v3'
export const useAxiosClient = () => {

  const executeRecaptcha  = useExecuteReCaptcha();

  const loginBefore = async () => {
    const captchaToken = await getCaptchaToken('login');
    //other desired stuff
  }
}

executeRecaptcha function is always available. Promise with Google Recaptcha token will be resolved as soon and reCAPTCHA script loaded.

Please note! Wrap your parent components with ReCaptchaProvider otherwise promises will be rejected immediately.

You can check GitHub repository for this package it has much cleaner source code with rich tests implemented.

Also, take a look at injectionDelay provider property + useSkipInjectionDelay hook in case you want to now blow up PageSpeed score of your website.

0

If anyone is coming here from Google, I solved this by moving my Recaptcha higher order component higher up in the hierarchy. My guess is that this component should never be rerendered.

0

I get the same error. And When I log executeRecaptcha this shows me. ƒ (e){if(!C||!C.execute)throw new Error("<GoogleReCaptchaProvider /> Google Recaptcha has not been loaded");return C.execute(x.current,{action:e})} I used this trick and I think the problem is gone:

const handleRecaptcha = useCallback(async () => { 
 if (!executeRecaptcha) {
      console.log("Execute recaptcha not yet available");
      return;
    }
try {
      const token = await executeRecaptcha("homepage");
      console.log("token", token);
      if (token) {
//do sth
    }
} catch (e) {
      console.log(e);
      setTimeout(() => handleRecaptcha(), 100);
    }
},[executeRecaptcha]);

Not the answer you're looking for? Browse other questions tagged or ask your own question.