When I explicitly render Recaptcha v2 and then reset it before removing it from the DOM, after ~40 seconds I get an error in the browser console.
I have a JSFiddle which can be used to reproduce the issue.
Here's the relevant code excerpt:
const recaptchaHolder = document.getElementById('...');
const recaptchaWidgetId = grecaptcha.render(recaptchaHolder, {/*...*/});
// then later
grecaptcha.reset(recaptchaWidgetId);
recaptchaHolder.parentElement.removeChild(recaptchaHolder);
The error that I get is:
Uncaught (in promise) Timeout
with the following stacktrace (the actual stacktrace might vary since it happens in heavily minified code):
setTimeout (async)
J @ recaptcha__en.js:100
(anonymous) @ recaptcha__en.js:285
tb @ recaptcha__en.js:284
mj @ recaptcha__en.js:456
(anonymous) @ recaptcha__en.js:458
I've tried to utilize the 'error-callback'
parameter from the documentation to catch this error, but that did not help - the error is still uncaught, and this callback does not get invoked.
Another observation: if I omit calling grecaptcha.reset
before removing the element from the DOM, then the error does not happen. However, it might result in inconsistent UI: if the user is challenged by recaptcha (for example, using images), and the element is simply removed from DOM without calling grecaptcha.reset
, then the challenge HTML is not cleaned up from the DOM.
I'm looking for ways of either handling the above mentioned error, or handling recaptcha removal in a different way (if I am doing it wrong now)
For reCaptcha v2, use: grecaptcha. reset();
One solution is to change the way you are submitting your form. Move the reCaptcha submission to a secondary server side page if possible. This will create a fresh condition where the interaction with Google is immediate.
After many hours I have found only this solution, see https://jsfiddle.net/4mLhcksq/
There is setTimeout
and 60 seconds (it could be shorter, I guess) pause before grecaptcha.reset()
and then another pause before removing Recaptcha element. Actually, I had the same problem even if I do not remove Recaptcha element, only reset it.
const holder = getRecaptchaHolder();
holder.style.display = 'none'; //element disappears for users
setTimeout(function() {
grecaptcha.reset(recaptchaWidgetId);
setTimeout(function() { //we have to wait a while before removing element
holder.parentElement.removeChild(holder);
}, 1000);
}, 60000);
I am not especially proud of this solution. Let us hope somebody will provide better one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With