2017-02-10 104 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)庫要容易得多。如果你願意,我會通過一個例子。 –