Skip to content

Instantly share code, notes, and snippets.

@WanLinLin
Last active July 5, 2020 02:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WanLinLin/49253f38b93fdf9bf4831710635d1dfb to your computer and use it in GitHub Desktop.
Save WanLinLin/49253f38b93fdf9bf4831710635d1dfb to your computer and use it in GitHub Desktop.
Recaptcha React Component
<!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>
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