Ошибка: в этом элементе уже отрендерилась reCAPTCHA при отправке OTP в ReactJs через 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.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;
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема решена Когда я изменил код 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». Может ли кто-нибудь объяснить причину этого, почему это происходит?

Programmer 16.03.2022 10:44

Другие вопросы по теме