Last active
July 5, 2020 02:28
-
-
Save WanLinLin/49253f38b93fdf9bf4831710635d1dfb to your computer and use it in GitHub Desktop.
Recaptcha React Component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>React Recaptcha Example</title> | |
</head> | |
<body> | |
<script> | |
function onRecaptchaLoaded() { | |
// code to inform recaptcha react component that recaptcha is loaded | |
// by setting isRecaptchaLoaded prop | |
} | |
</script> | |
<script src="https://www.google.com/recaptcha/api.js?onload=onRecaptchaLoaded" async defer></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import PropTypes from 'prop-types' | |
import {GOOGLE_RECAPTCHA_SITE_KEY} from 'constant' | |
/** | |
* recaptcha v2 I'm not a robot | |
* See https://developers.google.com/recaptcha/docs/display | |
*/ | |
class Recaptcha extends React.Component { | |
constructor() { | |
super() | |
this.ref = null | |
this.state = { | |
// is recaptcha element rendered, it can only be rendered once | |
rendered: false, | |
currentWidth: 0, | |
parentWidth: 0, | |
} | |
this.handleOnExpired = this.handleOnExpired.bind(this) | |
this.handleOnError = this.handleOnError.bind(this) | |
this.bindRef = this.bindRef.bind(this) | |
this.renderRecaptcha = this.renderRecaptcha.bind(this) | |
this.resetRecaptcha = this.resetRecaptcha.bind(this) | |
} | |
handleOnExpired() { | |
this.props.onResponseChange() | |
} | |
handleOnError() { | |
// Executed when recaptcha encounters an error (usually network | |
// connectivity) and cannot continue until connectivity is restored. | |
// | |
// If the error callback is not provided, recaptcha will pop an alert which | |
// is duplicated with our offline modal. So provide the callback and leave | |
// it blank. | |
} | |
bindRef(ref) { | |
this.ref = ref | |
} | |
renderRecaptcha() { | |
if (!this.props.isRecaptchaLoaded || this.state.rendered) { | |
return | |
} | |
this.widgetId = grecaptcha.render(this.ref, { | |
sitekey: GOOGLE_RECAPTCHA_SITE_KEY, | |
size: 'normal', | |
// executed when the recaptcha response expires (2 mins) and the user | |
// needs to re-verify | |
'expired-callback': this.handleOnExpired, | |
'error-callback': this.handleOnError, | |
// executed when the user passes the challenge. The g-recaptcha-response | |
// token is passed to the callback | |
callback: this.props.onResponseChange, | |
}) | |
this.setState({rendered: true}) | |
this.setState({parentWidth: this.ref.parentNode.clientWidth}) | |
this.setState({currentWidth: this.ref.clientWidth}) | |
} | |
resetRecaptcha() { | |
grecaptcha.reset(this.widgetId) | |
} | |
componentDidMount() { | |
this.renderRecaptcha() | |
} | |
componentDidUpdate(prevProps) { | |
if (!prevProps.shouldResetRecaptcha && this.props.shouldResetRecaptcha) { | |
this.resetRecaptcha() | |
} | |
this.renderRecaptcha() | |
} | |
render() { | |
const style = {display: 'inline-block'} | |
const {currentWidth, parentWidth} = this.state | |
return ( | |
// Scale recaptcha size to fit its parant width for small screen size mobile. | |
<div | |
ref={this.bindRef} | |
style={ | |
currentWidth !== 0 ? { | |
...style, | |
transform: `scale(${ currentWidth > parentWidth ? parentWidth / currentWidth : 1 })`, | |
transformOrigin: 0, | |
} : style | |
} | |
></div> | |
) | |
} | |
} | |
Recaptcha.propTypes = { | |
// The response is given when user passes the challenge. Should send the | |
// response along with form data to API to verify the user is not a robot. | |
// See https://developers.google.com/recaptcha/docs/verify | |
onResponseChange: PropTypes.func.isRequired, | |
isRecaptchaLoaded: PropTypes.bool.isRequired, | |
shouldResetRecaptcha: PropTypes.bool.isRequired, | |
} | |
export default Recaptcha |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment