繁体   English   中英

错误:当通过 Firebase 在 ReactJs 中发送 OTP 时,reCAPTCHA 已在此元素中呈现

[英]Error: reCAPTCHA has already been rendered in this element, when sending OTP in ReactJs via Firebase

我正在使用 Firebase 在用户手机号码上发送 OTP,我正在将它实现到 ReactJS。如果我第一次通过单击按钮发送 OTP,它工作正常,但如果我单击按钮超过 1 次而不刷新页面我得到错误“reCAPTCHA 已在此元素中呈现”。

我无法为此找到合适的解决方案。 我尝试了许多其他解决方案,通过谷歌搜索找到但没有人为我工作。 您的帮助/建议对我很有帮助。 谢谢你。

Firebase 发送 OTP 的代码:-

var recaptchaVerifier = new RecaptchaVerifier(
      "recaptcha-container",
      {
        size: "invisible",
      },
      auth
    );

    recaptchaVerifier.render();
    signInWithPhoneNumber(auth, mobileNumber, recaptchaVerifier)
      .then((confirmationResult) => {
        setFirebaseOtpResult(confirmationResult);
        setShowModal(true);
      })
      .catch((error) => {
        addToast("Something went wrong, please try again", {
          appearance: "error",
          autoDismiss: true,
        });
        console.log("error", error);
      });
  };

组件代码:-

import React, { useState } from "react";
import { useHistory } from "react-router-dom";
import { useSelector } from "react-redux";
import PhoneInput from "react-phone-number-input";
import "react-phone-number-input/style.css";
import { auth } from "../utils/firebase";
import { RecaptchaVerifier, signInWithPhoneNumber } from "firebase/auth";
import { Modal } from "react-bootstrap";
import "./forgot_password.style.css";
import { useToasts } from "react-toast-notifications";
import { API } from "../utils/api";

const ForgotPassword = () => {
  const history = useHistory();
  const { addToast } = useToasts();
  const { setting } = useSelector((state) => state.layoutSetting);
  const style = {
    color: setting.web_font_color,
    fontVariant: setting.web_font_variant,
    fontStyle: setting.web_font_style,
    fontWeight: setting.web_font_weight,
  };
  const phoneNumberValue = "";
  const [otp, setOtp] = useState("");
  const [mobileNumber, setMobileNumber] = useState("");
  const [showModal, setShowModal] = useState(false);
  const [firebaseOtpResult, setFirebaseOtpResult] = useState("");
  const [userId, setUserId] = useState("");

  const submitHandler = async (e) => {
    e.preventDefault();

    const params = { mobilenumber: mobileNumber };
    const config = {
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
      },
    };
    const { data } = await API.post("/foroget_passworod", params, config);
    if (data.code !== "SUCCESS") {
      addToast(data.message, {
        appearance: "error",
        autoDismiss: true,
      });
      return;
    }

    var recaptchaVerifier = new RecaptchaVerifier(
      "recaptcha-container",
      {
        size: "invisible",
      },
      auth
    );

    recaptchaVerifier.render();
    signInWithPhoneNumber(auth, mobileNumber, recaptchaVerifier)
      .then((confirmationResult) => {
        setFirebaseOtpResult(confirmationResult);
        setShowModal(true);
      })
      .catch((error) => {
        addToast("Something went wrong, please try again", {
          appearance: "error",
          autoDismiss: true,
        });
        console.log("error", error);
      });
    setUserId(data.data.id);
  };

  const submitHandlerOTP = (e) => {
    e.preventDefault();
    if (!otp.trim().length) {
      addToast("Please enter OTP code", {
        appearance: "error",
        autoDismiss: true,
      });
      return;
    }
    firebaseOtpResult
      .confirm(otp)
      .then((result) => {
        addToast("OTP verified", {
          appearance: "success",
          autoDismiss: true,
        });
        localStorage.setItem("user_id", JSON.stringify(userId));
        history.push("/change-password");
      })
      .catch((error) => {
        addToast("Invalid OTP enterd", {
          appearance: "error",
          autoDismiss: true,
        });
      });
  };

  return (
    <>
      <div className="login-form-container">
        <div className="login-register-form">
          <form onSubmit={submitHandler}>
            <PhoneInput
              placeholder="Mobile Number"
              international={true}
              defaultCountry="PK"
              countryCallingCodeEditable={false}
              value={phoneNumberValue}
              required
              onChange={setMobileNumber}
            />
            <div id="recaptcha-container"></div>
            <div className="button-box">
              <button
                type="submit"
                style={{ ...style, background: setting.web_background_color }}
              >
                <span>Send OTP</span>
              </button>
            </div>
          </form>
        </div>
      </div>

      {/* OTP Modal */}
      <Modal show={showModal}>
        <Modal.Header> Verify OTP </Modal.Header>
        <Modal.Body>
          <div className="row">
            <div className="col-md-12">
              <div className="login-form-container">
                <div className="login-register-form">
                  <form onSubmit={submitHandlerOTP}>
                    <input
                      type="number"
                      placeholder="Please enter OPT sent to you"
                      required
                      onChange={(e) => setOtp(e.target.value)}
                    />
                    <div id="recaptcha-container"></div>
                    <div className="button-box" style={{ textAlign: "center" }}>
                      <button
                        type="submit"
                        style={{
                          ...style,
                          background: setting.web_background_color,
                          border: "none",
                          padding: "7px 30px",
                          marginTop: "25px",
                        }}
                      >
                        <span>Verify</span>
                      </button>
                      <button
                        type="button"
                        style={{
                          ...style,
                          background: setting.web_background_color,
                          border: "none",
                          padding: "7px 30px",
                          marginTop: "25px",
                          marginLeft: "10px",
                        }}
                        onClick={() => setShowModal(false)}
                      >
                        <span>Close</span>
                      </button>
                    </div>
                  </form>
                </div>
              </div>
            </div>
          </div>
        </Modal.Body>
      </Modal>
    </>
  );
};

export default ForgotPassword;

firebase.js

import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';

const config = {
    apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
    authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
    storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.REACT_APP_FIREBASE_APP_ID
};

const app = initializeApp(config);
export const auth = getAuth(app); 
export default app;

问题已解决当我更改 firebase 代码时

从:-

var recaptchaVerifier = new RecaptchaVerifier(
   "recaptcha-container",
    {
     size: "invisible",
    },
      auth
);
recaptchaVerifier.render();

到:-

if(!window.recaptchaVerifier){
      window.recaptchaVerifier = new RecaptchaVerifier(
        "recaptcha-container",
        {
          size: "invisible",
        },
        auth
      );
 }
window.recaptchaVerifier.render();

当 object 已经存在时,我们不需要创建 RecaptchaVerifier 的 object。

我希望这可以帮助未来的访客,

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM