reactjs - How to build a firebase auth RecaptchaVerifier React Component? - Stack Overflow

admin2025-04-17  2

I am using firebase auth and I wanted to add SMS MFA Verfication. I had struggled a lot integrating the required RecaptchaVerifier with my React Components. So I ended up trying to build a RecaptchaButton. Basically its job is to render a button and then perform a recaptch activated action and return the verifier. Here's what that looks like

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}) {

    //Force the Button to rerender always, since Recaptcha attaches itself to the button and will stop working if a previous instance of itself has already attached itself to the button
    const [randomizedKey,setRandomizedKey]=useState(randomAlphaNumeric(64));

    useEffect(()=>{

        //With this I am trying to avoid double renders. RecaptchaVerifier.clear doesn't actually work and the verifier will still be active, forcing us to use the verifier of the previous render (due to strict mode)
        if(!window.recaptchaRepo || !window.recaptchaRepo[randomizedKey]){

            const recaptchaVerifier = new RecaptchaVerifier(AuthSingleton.get().firebaseAuth, randomizedKey, {
                "size": "invisible",
                "callback": async function(response) {
                    //Recaptcha insist on being the only one allowed to handle the onClick event which is extremely annoying
                    onVerified(recaptchaVerifier);
                },

                    // Response expired. Ask user to solve reCAPTCHA again.
                    onError(new Error("Recaptcha expired"));
                }
                ,
                "error-callback": function(e) {
                    onError(e);
                }

            });
            //Despite this, Recaptcha Still finds a way to spit out errors
            try{
                const grepid=recaptchaVerifier.render().catch(()=>{});
            }catch(e){
            }

            window.recaptchaRepo??={};
            //This will cause a large buildup of unused RecaptchaVerfiers but theres no actual way to reset or release them.
            window.recaptchaRepo[randomizedKey]=recaptchaVerifier;
        }

    },[]);



    // Forcibly renrende the button
    return (
        <Bootstrap.Button {...props}  id={randomizedKey} key={randomizedKey} />
    );


}

This will still produce errors like this (and lots of em):

Uncaught TypeError: n is null
    N recaptcha__en.js:514
    F recaptcha__en.js:152
    setTimeout handler*d< recaptcha__en.js:209
    d recaptcha__en.js:152
    T recaptcha__en.js:101
    <anonymous> recaptcha__en.js:1123
    E recaptcha__en.js:538
    E recaptcha__en.js:538
    d recaptcha__en.js:178
    next recaptcha__en.js:401
    p recaptcha__en.js:258
    promise callback*I recaptcha__en.js:258
    H recaptcha__en.js:259
    A recaptcha__en.js:258
    g recaptcha__en.js:534
    g recaptcha__en.js:538
    g recaptcha__en.js:547
    WS recaptcha__en.js:749
    L recaptcha__en.js:517
    A recaptcha__en.js:280
    l recaptcha__en.js:322
    d recaptcha__en.js:145
    l recaptcha__en.js:328
    g recaptcha__en.js:547
    ym recaptcha__en.js:985
    R recaptcha__en.js:445
    d recaptcha__en.js:207
    WS recaptcha__en.js:749
    L recaptcha__en.js:517
    A recaptcha__en.js:280
    l recaptcha__en.js:322
    d recaptcha__en.js:145
    l recaptcha__en.js:328
    d recaptcha__en.js:206
    O recaptcha__en.js:445
    O recaptcha__en.js:411
    g recaptcha__en.js:553
    d recaptcha__en.js:147
    MU recaptcha__en.js:594
    N recaptcha__en.js:478
    makeRenderPromise recaptcha_verifier.ts:246
    render recaptcha_verifier.ts:172
    ReCaptchaButton ReCaptchaButton.jsx:52

So far, this works for the most part. Unfortunately it is far from a clean solution. So is there a better way to integrate firebase auth RecaptchaVerifier into React? Or is there a way to bypass the firebase Recaptcha implmentation in favor of something like this?

I just want it to work without spitting out loads of errors

转载请注明原文地址:http://anycun.com/QandA/1744889300a89059.html