You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am trying to build ReCaptchaButton component in React JS. For this to work I need to be able to create a RecaptchaVerfier as soon as the elment is mounted and destroy it as soon as it is unmounted. Unfortunately, the destroy part doesn't work. (In Strict Mode, React mounts a component, then immedietly unmounts it and then mounts a new instance, to enforce re-usability)
This wouldn't be a problem, but unfortunately, recaptchaVerifier.clear doesn't seem to actually do anything. Meaning, it stays attached to the dom (which react keeps as is) even as the component itself unmounts. The next mount then encounters an already captcha infested button and then throws an Error.
The only way I've been able to sort of make this work, is by anticipating the remount using a window.alreadyMounted variable and then reuse the verfier of the already unmounted component. This is an ugly hack which itself spits out a bunch of errors, namely:
Uncaught TypeError: n is null
N recaptcha__en.js:514
F recaptcha__en.js:152
and that is despite my efforts to suppress thrown errors. From what I've found, nobody has yet been able to integrated firebase embedded RecaptchaVerfier into a clean React component, simply because .clear doesn't actually clear the component.
Steps and code to reproduce issue
Here's the RecaptchaButton. Simply Mounting it once will spit out the Error: reCAPTCHA has already been rendered in this element N recaptcha__en.js:477 Error
import {
RecaptchaVerifier
} from "firebase/auth";
import {useState,useContext,useEffect} from 'react';
import * as Bootstrap from 'react-bootstrap';
import {AuthSingleton} from '../auth/AuthSingleton.js';
import * as auth from 'firebase/auth';
//Need these because recaptch is a mess
function randomAlphaNumeric(length = 64) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
const randomValues = new Uint8Array(length);
crypto.getRandomValues(randomValues);
for (let i = 0; i < length; i++) {
result += chars[randomValues[i] % chars.length];
}
return result;
}
export function ReCaptchaButton({onVerified,onError,...props}) {
const [randomizedKey,setRandomizedKey]=useState(randomAlphaNumeric(64));
useEffect(()=>{
const recaptchaVerifier = new RecaptchaVerifier(AuthSingleton.get().firebaseAuth, randomizedKey, {
"size": "invisible",
"callback": async function(response) {
// reCAPTCHA solved, you can proceed with
// phoneAuthProvider.verifyPhoneNumber(...).
onVerified(recaptchaVerifier);
},
"expired-callback": function() {
// Response expired. Ask user to solve reCAPTCHA again.
onError(new Error("Recaptcha expired"));
}
,
"error-callback": function(e) {
onError(e);
}
});
try{
recaptchaVerifier.render().catch(()=>{});
}catch(e){
}
// This will be executed as soon as the component unmounts
return ()=>{
// This doesn't work
recaptchaVerifier.clear();
};
},[]);
return (
<Bootstrap.Button {...props} id={randomizedKey} key={randomizedKey} />
);
}
The text was updated successfully, but these errors were encountered:
Some other users have encountered some nuances to using Recaptcha with React. Could you take a look at this StackOverflow thread and see if it solves your issue? Thanks.
@DellaBitta I did see that Thread. But it didn't make sense to me because
A It makes no mention of the actual button (or clickable div) that is required in the current version of RecaptchaVerifier. Recaptcha Verfier attaches an OnClick listener to the element with the passed id. This cannot easily be recreated using innerHTML from within React. It might have worked in 2018 (from when the post was made) but it doesn't work anymore
B It doesn't make sense how .clear would not actually clear the div (as the poster suggests.) The documentation isn't clear on that either. If the .clear doesnt clear a div of Captcha influence, then what does it do?
Operating System
Manjaro
Environment (if applicable)
node 23.3, React
Firebase SDK Version
"firebase": "^11.1.0",
Firebase SDK Product(s)
Auth
Project Tooling
It is using react 18.3 with vite 6.0.01.
Detailed Problem Description
I am trying to build ReCaptchaButton component in React JS. For this to work I need to be able to create a RecaptchaVerfier as soon as the elment is mounted and destroy it as soon as it is unmounted. Unfortunately, the destroy part doesn't work. (In Strict Mode, React mounts a component, then immedietly unmounts it and then mounts a new instance, to enforce re-usability)
This wouldn't be a problem, but unfortunately, recaptchaVerifier.clear doesn't seem to actually do anything. Meaning, it stays attached to the dom (which react keeps as is) even as the component itself unmounts. The next mount then encounters an already captcha infested button and then throws an Error.
The only way I've been able to sort of make this work, is by anticipating the remount using a window.alreadyMounted variable and then reuse the verfier of the already unmounted component. This is an ugly hack which itself spits out a bunch of errors, namely:
and that is despite my efforts to suppress thrown errors. From what I've found, nobody has yet been able to integrated firebase embedded RecaptchaVerfier into a clean React component, simply because .clear doesn't actually clear the component.
Steps and code to reproduce issue
Here's the RecaptchaButton. Simply Mounting it once will spit out the Error:
reCAPTCHA has already been rendered in this element N recaptcha__en.js:477 Error
The text was updated successfully, but these errors were encountered: