【问题标题】:React recaptcha constructor in useEffect runs before first render在第一次渲染之前运行 useEffect 中的 React recaptcha 构造函数
【发布时间】:2021-03-05 07:31:11
【问题描述】:

也许我误解了useEffect的概念,但我认为它取代了componentDidMountcomponentDidUpdatecomponentWillUnmount,所以它的第一次运行是在组件渲染之后。 我想将 firebase 集成到我的 react 项目中,但是在我看来 useEffect 在渲染方法之前运行,因为如果我按照以下方式使用它,它会给我这个错误

reCAPTCHA 容器未找到或已包含内部 元素!

const PhoneVerificationModal = (props) => {
    useEffect(() => {
        const firebaseConfig = {
            apiKey: "...",
            authDomain: "...",
            databaseURL: "...",
            projectId: "...",
            storageBucket: "...",
            messagingSenderId: "...",
            appId: "..."
        };

        firebase.initializeApp(firebaseConfig);
        window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
            'size': 'invisible',
            'callback': function (response) {
                // reCAPTCHA solved, allow signInWithPhoneNumber.
                firebaseSubmit();
            }
        });

    }, []);

    const [open, toggleOpen] = useState(props.open);

    useEffect(() => {
        toggleOpen(props.open);
    });

    const sendVerificationCode = () => {
        if (props.phone) {
            console.log(props.phone);
            let phoneNumber = props.phone;
            var appVerifier = window.recaptchaVerifier;
            firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
                .then(function (confirmationResult) {
                    console.log(confirmationResult);
                    window.confirmationResult = confirmationResult;
                }).catch(function (error) {
                });
        }

    }

    const firebaseSubmit = () => {

    }
    return (
        <Modal open={open} key={open} closeModal={props.closeModal}>
            <div className={classes.PhoneVerificationModalInner}>
                <div className={classes.headerRow}>
                </div>
                <div className={classes.narrowCol}>
                    <div id="recaptcha-container"></div>
                    <Button
                        className={classes.button}
                        rightIcon={Images.arrow}
                    >Continue</Button>
                </div>
            </div>
        </Modal>
    )
}

如果我用 setTimeout 向 recaptcha 构造函数添加延迟,它运行没有问题。那么构造函数怎么找不到元素,即使它是由于useEffect而渲染的呢?

【问题讨论】:

  • 在调用 RecaptchaVerifier 之前,你有没有尝试过 console.log(document.querySelector("#'recaptcha-container'")),看看是否元素存在于 dom 中?
  • @lissettdm 它说它为空。但怎么可能呢?我认为useEffect的第一次运行是在渲染之后,因此元素应该存在
  • 是的,它在第一次渲染后运行,参见stackblitz.com/edit/react-mgcsdg。尝试删除与firebase相关的代码,看看它是否打印了该项目。
  • 我认为错误在 Modal 组件内部,在它如何呈现子组件方面。
  • 尝试将此
    移到模态组件之外。仅用于测试目的

标签: javascript reactjs firebase-authentication


【解决方案1】:

我一遍又一遍地尝试这个,这个(隐形验证码)对我有用。

我的方法是仅在提交时才调用验证码。 useEffect 不是必需的,如果用户花很长时间输入数字并提交,您的验证码也不会过期。

您需要将其添加到您的脑海中。这提供了 grecaptcha.reset 功能

<script src="https://www.google.com/recaptcha/api.js" async defer></script>

创建一个提交时应该调用的 onSubmit 按钮。

   const onSubmit = async () => {

        window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('mycode', {
            'size': 'invisible',
            'callback': async function(res) {
                
                console.log('captcha code', res)
                //do your sign in with phone here.


            },
            'expired-callback': function() {
                grecaptcha.reset();
            }
    
        });


        window.recaptchaVerifier.render().then(function (widgetId) {       
            window.recaptchaWidgetId = widgetId;
            grecaptcha.execute(window.recaptchaWidgetId);
        })
        
        
     //https://developers.google.com/recaptcha/docs/invisible#js_api

}

在您的渲染中,您需要具有以下内容

<div id="mycode" />

当您点击提交按钮时(在您捕获手机/电话号码后),Recaptcha 将确定是否需要进行验证码检查。然后,您将获得可以提交到后端进行验证的代码。

【讨论】:

  • 嗨,显然问题与模态组件呈现其子级的方式有关。
  • 您的模态不能使用 Portal,如果它使用 Portal,它将无法工作。我有同样的问题,因此我意识到在提交时获取验证码比在页面加载时加载验证码要好得多。带有 id 的 div 肯定会在那里。
猜你喜欢
  • 1970-01-01
  • 2021-10-16
  • 2022-01-20
  • 2020-01-23
  • 2020-01-11
  • 2021-03-18
  • 2021-05-03
  • 2020-01-29
  • 2022-11-26
相关资源
最近更新 更多