Reactjs 用Redux表单实现不可见的reCAPTCHA

Reactjs 用Redux表单实现不可见的reCAPTCHA,reactjs,recaptcha,redux-form,Reactjs,Recaptcha,Redux Form,我正在尝试使用React和Redux表单实现。通常,不可见的reCAPTCHA工作流是: 呈现“不可见”验证码,返回其小部件ID 调用grecaptcha。使用小部件的ID执行。如有必要,将提示用户解决质询。结果将传递给呈现验证码时指定的回调函数 提交表格和验证码结果 我创建了一个React组件,用于Redux表单的字段,该组件在grecaptcha之后呈现验证码并更新表单状态。调用execute: class ReCaptcha extends React.Component { rend

我正在尝试使用React和Redux表单实现。通常,不可见的reCAPTCHA工作流是:

  • 呈现“不可见”验证码,返回其小部件ID
  • 调用
    grecaptcha。使用小部件的ID执行
    。如有必要,将提示用户解决质询。结果将传递给呈现验证码时指定的回调函数
  • 提交表格和验证码结果
  • 我创建了一个React组件,用于Redux表单的
    字段
    ,该组件在
    grecaptcha之后呈现验证码并更新表单状态。调用execute

    class ReCaptcha extends React.Component {
      render() {
        return <div ref={div => this.container=div} />
      }
    
      componentDidMount() {
        const { input: { onChange }, sitekey } = this.props
        grecaptcha.render(this.container, {
          sitekey,
          size: "invisible",
          callback: onChange
        })
      }
    }
    
    类ReCaptcha扩展了React.Component{
    render(){
    返回此。container=div}/>
    }
    componentDidMount(){
    const{input:{onChange},sitekey}=this.props
    grecaptcha.render(这个容器{
    sitekey,
    尺寸:“隐形”,
    回调:onChange
    })
    }
    }
    
    但是,我不知道如何或在何处调用
    grecaptcha.execute
    以及用户提交表单时的小部件ID。我无法在
    onSubmit
    中调用它,因为在那里无法访问小部件ID。我可以在呈现CAPTCHA后立即调用它,但如果用户需要解决CAPTCHA,则在表单呈现后会提示用户立即解决


    这显示了我到目前为止所取得的成就。

    使用onSubmit属性调用grecaptcha.execute(),并将数据回调指向“real”onSubmit函数

    let refToMyWidget;
    const { handleSubmit } = this.props;
    
    componentDidMount() {
      if (window.grecaptcha) {
        refToMyWidget = window.grecaptcha.render(this.container, {
          sitekey: "xxxx",
          size: "invisible",
          callback: handleSubmit(this.actuallySubmit)
        })
      }
    }
    
    preSubmit() {
      if(!window.grecaptcha) {
        return;
      }
      window.grecaptcha.execute(this.refToMyWidget)
    }
    
    actuallySubmit() {
      // submission logic here
    }
    
    render() {
      return (
        <form onSubmit={handleSubmit(this.preSubmit)}>
            <Field name="foo" component="input" />
            <button>Submit</button>
        </form>
      )
    }
    
    让refToMyWidget;
    const{handleSubmit}=this.props;
    componentDidMount(){
    如果(window.grecaptcha){
    refToMyWidget=window.grecaptcha.render(this.container{
    站点密钥:“xxxx”,
    尺寸:“隐形”,
    回调:handleSubmit(this.actuallySubmit)
    })
    }
    }
    预先提交(){
    如果(!window.grecaptcha){
    返回;
    }
    window.grecaptcha.execute(this.refToMyWidget)
    }
    实际提交(){
    //这里的提交逻辑
    }
    render(){
    返回(
    提交
    )
    }
    

    注意:我还没有测试过这段代码,但它应该或多或少是正确的。如果您在将grecaptcha加载到页面/表单时遇到问题,我发现代码非常有用。

    我必须使不可见的reCAPTCHA对我有效,因为可见的reCAPTCHA没有响应。这是我实现的示例

    首先要做的是在主体中添加下面的标记(或者您可以使用)

    
    
    我的工作代码的简化版本:

    import React from 'react';
    
    class YourComponent extends React.Component {
      componentDidMount() {
        // Create a script to make sure the reCAPTCHA API is called.
        const script = document.createElement('script');
        script.text = `
          var onloadCallback = function() {
            console.log('grecaptcha is ready');
          };
        `;
        document.body.appendChild(script);
    
        // We will render reCAPTCHA after the page is loaded,
        // because we want to bind our own submit methods.
        window.addEventListener('load', this.onLoad);
      }
    
      // Runs once the form is submitted.
      onRecaptcha = (e) => {
        e.preventDefault();
        const { grecaptcha } = window;
        grecaptcha.execute();
      };
    
      // Real submit function.
      onSubmit = (token) => {
        // I'm not sure what token could be if recaptcha fails.
        // In my case it seems successful and returns a long string.
        console.log(token);
    
        // Your real action goes below...
      };
    
      onLoad = () => {
        // Now we define our reCAPTCHA
        if (window.grecaptcha) {
          const { grecaptcha } = window;
          grecaptcha.render('recaptcha', { // div#recaptcha
            sitekey  : '',
            size     : 'invisible',
            callback : this.onSubmit
          });
        }
      };
    
      render() {
        return (
          <div>
            <Helmet>
              <script
                src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
                async
                defer
              />
            </Helmet>
            <form onSubmit={this.onRecaptcha}>
              <div id="recaptcha" />
              <button type="submit">Submit</button>
            </form>
          </div>
        );
      }
    }
    
    export default YourComponent;
    
    从“React”导入React;
    类YourComponent扩展React.Component{
    componentDidMount(){
    //创建一个脚本以确保调用了reCAPTCHA API。
    const script=document.createElement('script');
    script.text=`
    var onloadCallback=函数(){
    log('grecaptcha准备就绪');
    };
    `;
    document.body.appendChild(脚本);
    //我们将在页面加载后呈现reCAPTCHA,
    //因为我们想绑定我们自己的提交方法。
    window.addEventListener('load',this.onLoad);
    }
    //提交表单后运行。
    onRecaptcha=(e)=>{
    e、 预防默认值();
    const{grecaptcha}=window;
    grecaptcha.execute();
    };
    //真正的提交功能。
    onSubmit=(令牌)=>{
    //我不确定如果recaptcha失败会是什么令牌。
    //在我的例子中,它似乎成功并返回一个长字符串。
    console.log(令牌);
    //你的实际行动如下。。。
    };
    onLoad=()=>{
    //现在我们定义我们的reCAPTCHA
    如果(window.grecaptcha){
    const{grecaptcha}=window;
    render('recaptcha',{//div#recaptcha
    站点密钥:“”,
    大小:'不可见',
    回调:this.onSubmit
    });
    }
    };
    render(){
    返回(
    提交
    );
    }
    }
    导出默认组件;
    
    通过这种方式,您可以在react中的任何位置实施它

    import React, { Component } from "react";
    
        export default class Test extends Component {
    
          componentWillMount = () => {
            const script = document.createElement("script");
            script.src = "https://www.google.com/recaptcha/api.js";
            script.async = true;
            script.defer = true;
            document.body.appendChild(script);
    
            window.addEventListener("load", this.onLoad);
          };
    
          onLoad = () => {
            if (window.grecaptcha) {
              window.grecaptcha.render("recaptcha", {
                sitekey: "",
                size: "invisible",
                callback: this.onCaptcheCompleted
              });
            }
          };
          onCaptcheCompleted = e => {
            //do what ever you want
            console.log(e);
          };
    
          render() {
            return (
              <div id="recaptcha">
                <input />
                <button onClick={() => window.grecaptcha.execute()} />
              </div>
            );
          }
        }
    
    import React,{Component}来自“React”;
    导出默认类测试扩展组件{
    组件将装入=()=>{
    常量脚本=document.createElement(“脚本”);
    script.src=”https://www.google.com/recaptcha/api.js";
    script.async=true;
    script.defer=true;
    document.body.appendChild(脚本);
    window.addEventListener(“加载”,this.onLoad);
    };
    onLoad=()=>{
    如果(window.grecaptcha){
    window.grecaptcha.render(“recaptcha”{
    sitekey:“”,
    尺寸:“隐形”,
    回调:this.onCaptcheCompleted
    });
    }
    };
    onCaptcheCompleted=e=>{
    //你想干什么就干什么
    控制台日志(e);
    };
    render(){
    返回(
    window.grecaptcha.execute()}/>
    );
    }
    }
    
    我发现使用库更容易。如果你愿意,我可以举个例子。
    import React, { Component } from "react";
    
        export default class Test extends Component {
    
          componentWillMount = () => {
            const script = document.createElement("script");
            script.src = "https://www.google.com/recaptcha/api.js";
            script.async = true;
            script.defer = true;
            document.body.appendChild(script);
    
            window.addEventListener("load", this.onLoad);
          };
    
          onLoad = () => {
            if (window.grecaptcha) {
              window.grecaptcha.render("recaptcha", {
                sitekey: "",
                size: "invisible",
                callback: this.onCaptcheCompleted
              });
            }
          };
          onCaptcheCompleted = e => {
            //do what ever you want
            console.log(e);
          };
    
          render() {
            return (
              <div id="recaptcha">
                <input />
                <button onClick={() => window.grecaptcha.execute()} />
              </div>
            );
          }
        }