Firebase 电话身份验证 Recaptcha 验证程序未设置为窗口/加载

Rec*_*con 5 javascript firebase reactjs firebase-authentication

我正在尝试将 RecaptchaVerifier 加载到我的 React 类中,以便我可以为我的 Web 应用程序启用电话身份验证。但是,当我提交电话号码时,出现以下错误:

"signInWithPhoneNumber failed: Second argument "applicationVerifier" must be an implementation of firebase.auth.ApplicationVerifier." 此错误的整个控制台日志

我记录了 window.recaptchaVerifier,发现它默默地出错,错误代码如下:

TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.invokeGetter (<anonymous>:2:14) 控制台错误

Recaptcha 甚至不渲染,并且 window.repcaptchaVerfier.render() 方法抛出另一个错误(似乎该部分在文档中是可选的,所以我将其删除)。

  constructor(props) {
    super(props);

    this.state = {
      sendOTP: false,
      phone_number: "",
      currentUser: null,
      otp: "",
      isButtonDisabled: true,
      error: '',
      cardAnimation: 'cardHidden',
    };
  }

  componentDidMount() {
    this.setupRecaptcha();

    setTimeout(() => {
      this.setState({cardAnimation: ""});
    }, 700);

    // window.recaptchaVerifier.render().then(widgetId => {
    //   window.recaptchaWidgetId = widgetId;
    // });
    // Removed, since it errors on load with this code.

  }

  setupRecaptcha = () => {
    window.recaptchaVerifier = new this.props.firebase.recaptchaVerifier(
      'recaptcha-container',
      {
        size: "normal",
        callback: response => {
          // reCAPTCHA solved, allow signInWithPhoneNumber.
          // ...
          this.setState({ isButtonDisabled: false });
        },
        "expired-callback": response => {
          // Response expired. Ask user to solve reCAPTCHA again.
          // ...
          this.setState({ isButtonDisabled: true, error: "Recaptcha Expired. Please try again." });

        }
      }
    );
    console.log(window.recaptchaVerifier)
    // Here is where i get the silent error about "strict" mode.
  };

  handleLogin = () => {
    let appVerifier = window.recaptchaVerifier;
    this.props.firebase.doSignInWithPhoneNumber(this.state.phone_number, appVerifier).then(confirmationResult => {
      this.setState({sendOTP: true});
      window.confirmationResult = confirmationResult;
    }).catch(err => {
      this.setState({error: err})
    })
  };

  handleOTPCheck = () => {
    window.confirmationResult
      .confirm(this.state.otp)
      .then(function(result) {
        // User signed in successfully.
        console.log(result);
        // ...
      })
      .catch(function(error) {
        // User couldn't sign in (bad verification code?)
        // ...
      });
  };

  handleSubmit(event) {
    event.preventDefault();
  }

  onChange = event => {
    this.setState({ [event.target.name]: event.target.value });
  };

  render() {
    const { phone_number, otp, error } = this.state;

    const isInvalid = phone_number === '';
    const { classes } = this.props;

    return (
      <div
        className={classes.pageHeader}
        style={{
          backgroundImage: "url(" + backgroundImage + ")",
          backgroundSize: "cover",
          backgroundPosition: "top center"
        }}
      >
        <div className={classes.container}>
          <Grid container justify="center">
            <Grid item xs={12} sm={12} md={4}>
              <Card className={classes[this.state.cardAnimation]}>
                <form className={classes.form}>
                  <CardHeader color="primary" className={classes.cardHeader}>
                    <Typography variant={'h4'}>Login</Typography>
                  </CardHeader>
                  <CardBody>
                    <TextField
                      label={"Phone Number"}
                      id="phone_number"
                      name={"phone_number"}
                      fullWidth

                      InputProps={{
                        endAdornment: <InputAdornment position="end"><Phone/></InputAdornment>,
                      }}
                      type={"tel"}
                    />
                    <TextField
                      label="One-Time Password"
                      id="otp"
                      name={"otp"}
                      fullWidth

                      InputProps={{
                        endAdornment: <InputAdornment position="end"><Lock/></InputAdornment>,
                      }}

                      type={'password'}
                      autoComplete={'false'}
                    />
                  </CardBody>
                  <div id={'recaptcha-container'}/>

                  <p className={classes.divider}>Standard messaging rates may apply.</p>

                  <CardFooter className={classes.cardFooter}>
                    <Button color="primary" size="large" onClick={this.handleLogin}>
                      Verify
                    </Button>
                  </CardFooter>

                </form>
              </Card>
            </Grid>
          </Grid>
        </div>
        <Footer whiteFont />
      </div>
    );
  }
}
const SignInForm = compose(
  withRouter,
  withFirebase,
)(SignInFormBase);
/// this is then rendered in a functional react component in this page
Run Code Online (Sandbox Code Playgroud)

我有一个高阶组件可以为我提供 firebase 上下文。this.props.firebase.recaptchaVerifier我的 setupRecaptcha 函数中调用的函数是:

class Firebase() {
    constructor() {
        // initialise firebase etc
        this.authRef = app().auth;
        this.auth.useDeviceLanguage();
    }
    recaptchaVerifier = (container, parameters) =>
        this.authRef.RecaptchaVerifier(container, parameters);

}
Run Code Online (Sandbox Code Playgroud)

我真的很难过!

编辑:

我设法修复它。我将“新”语句移至我的上下文提供程序中:

recaptchaVerifier = (container, params) => {
    return new this.authRef.RecaptchaVerifier(container, params);
  };
Run Code Online (Sandbox Code Playgroud)
    setupRecaptcha = () => {
        window.recaptchaVerifier = this.props.firebase.recaptchaVerifier('recaptcha-container', {
            'size': 'normal',
            'callback': response => {
                // reCAPTCHA solved, allow signInWithPhoneNumber.
                this.setState({isButtonDisabled: false});
            },
            'expired-callback': response => {
                // Response expired. Ask user to solve reCAPTCHA again.
                this.setState({isButtonDisabled: true, error: "Recaptcha Expired. Please try again."});
            }
        });
        window.recaptchaVerifier.render().then(widgetId => {
            window.recaptchaWidgetId = widgetId;
        });
    };
Run Code Online (Sandbox Code Playgroud)

Rec*_*con 2

我设法修复它。我将“新”语句移至我的上下文提供程序中:

// In context.js
recaptchaVerifier = (container, params) => {
    return new this.authRef.RecaptchaVerifier(container, params);
  };
// in my component
    setupRecaptcha = () => {
        window.recaptchaVerifier = this.props.firebase.recaptchaVerifier('recaptcha-container', {
            'size': 'normal',
            'callback': response => {
                // reCAPTCHA solved, allow signInWithPhoneNumber.
                this.setState({isButtonDisabled: false});
            },
            'expired-callback': response => {
                // Response expired. Ask user to solve reCAPTCHA again.
                this.setState({isButtonDisabled: true, error: "Recaptcha Expired. Please try again."});
            }
        });
        window.recaptchaVerifier.render().then(widgetId => {
            window.recaptchaWidgetId = widgetId;
        });
    };```
Run Code Online (Sandbox Code Playgroud)