2017-02-10 78 views
8

我试图用React和Redux窗体实现Invisible reCAPTCHA。通常,隐形reCAPTCHA工作流程如下:使用Redux表单实现隐形reCAPTCHA

  1. 呈现“不可见”CAPTCHA,返回其窗口小部件ID。
  2. 调用grecaptcha.execute与小部件的ID。如有必要,用户将被提示解决挑战。结果被传递给在渲染CAPTCHA时指定的回调函数。
  3. 与CAPTCHA结果一起提交表格。

我创建了旨在与终极版Form的Field呈现的CAPTCHA并更新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 
    }) 
    } 
} 

不过,我不知道如何或者在用户提交表单时将grecaptcha.execute与小部件ID一起呼叫的位置。我无法在onSubmit中调用它,因为那里无法访问控件ID。我可以在渲染CAPTCHA后立即在ReCaptcha中调用它,但如果用户需要解开CAPTCHA,他会在窗体渲染后立即提示。

这个minimal working example显示了我迄今取得的成就。

回答

0

使用onSubmit prop调用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> 
) 
} 

N.b.我没有测试过这个代码,但它应该是或多或少的正确。如果您在加载grecaptcha到页面/表单时遇到麻烦,我发现代码非常有用。

0

我不得不为我做隐形的reCAPTCHA工作,因为可见的工作没有响应。 Here是我实施的例子。

首先要做的是将下面的标签添加到正文(或者您可以使用react-helmet)。

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script> 

我的工作代码版本简化:

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; 
+0

我已经想通了,它与[scriptjs(https://github.com/ded/script.js)库要容易得多。如果你愿意,我会通过一个例子。 –