Я использую 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.info("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.info("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;



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема решена Когда я изменил код 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();
We don't need to create object of RecaptchaVerifier when an object already exists.
Я надеюсь, что это может помочь будущим посетителям,
Это работает для меня, спасибо. Я не могу понять, использую ли я окно, а не var, все работает нормально, без ошибок. Но если я использую var вместо окна при объявлении/назначении значения переменной/объекту, это дает ошибку «reCAPTCHA уже была отображена в этом элементе при отправке OTP в ReactJs через Firebase». Может ли кто-нибудь объяснить причину этого, почему это происходит?