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

RecaptchaClear doesn't actually work #8747

Open
White-waluigi opened this issue Jan 31, 2025 · 3 comments
Open

RecaptchaClear doesn't actually work #8747

White-waluigi opened this issue Jan 31, 2025 · 3 comments

Comments

@White-waluigi
Copy link

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:


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} />
	);


}
@White-waluigi White-waluigi added new A new issue that hasn't be categoirzed as question, bug or feature request question labels Jan 31, 2025
@google-oss-bot
Copy link
Contributor

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@jbalidiong jbalidiong added api: auth needs-attention and removed needs-triage new A new issue that hasn't be categoirzed as question, bug or feature request labels Jan 31, 2025
@DellaBitta
Copy link
Contributor

Hi @White-waluigi,

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.

@White-waluigi
Copy link
Author

@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?

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

No branches or pull requests

4 participants