[英]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.