I have the following React component for a contact form:
import React from 'react'
import ReCAPTCHA from "react-google-recaptcha";
import {Container, Row, Col, Form, Button } from 'react-bootstrap'
import '../styles/contact.css'
class Contact extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
name: '',
email: '',
company: '',
content: '',
showSuccess: false,
submitting: false,
verified: false,
reply: ''
};
this.handleSuccess = this.handleSuccess.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
this.onChange = this.onChange.bind(this);
}
onChange = (value) => {
console.log("Captcha value:", value);
this.setState({
verified: true
})
};
handleInputChange = event => {
const target = event.target
const value = target.value
const name = target.name
this.setState({
[name]: value,
})
}
handleSuccess = () => {
this.setState({
name: '',
email: '',
company: '',
content: '',
showSuccess: true,
submitting: false,
})
}
handleSubmit = event => {
const url = 'https://xxxxxxxx.execute-api.eu-central-1.amazonaws.com/dev/email/send';
this.setState({
submitting: true
})
const payload = {
name: this.state.name,
email: this.state.email,
company: this.state.company,
content: this.state.content
}
if (this.state.verified) {
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
.then(this.handleSuccess)
.catch(error => alert(error))
event.preventDefault()
}
else {this.setState({reply: "Please verify the ReCaptcha."})}
}
render() {
return (
<section id="contact" name="#contact">
<Container>
<Row className="align-items-center">
<Col lg={{span: 5, order: 1}} xs={{ span: 12, order: 2}} className="form-background">
<Form id="contact-form-bottom" onSubmit={this.handleSubmit}>
<h4 className="h4">Don't be shy, say hi!</h4>
<Form.Group controlId="formBasicEmail">
<Form.Label>Full Name</Form.Label>
<Form.Control
as="input"
type="text"
placeholder="Enter your first name & surname"
name="name"
value={this.state.name}
onChange={this.handleInputChange}
required
/>
</Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control
as="input"
type="email"
placeholder="Enter your email address"
name="email"
value={this.state.email}
onChange={this.handleInputChange}
required
/>
<Form.Text className="text-muted">
We'll never share your email with anyone else.
</Form.Text>
</Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Label>Company Name</Form.Label>
<Form.Control
as="input"
type="text"
placeholder="Enter the name of your company"
name="company"
value={this.state.company}
onChange={this.handleInputChange}
required
/>
</Form.Group>
<Form.Group controlId="exampleForm.ControlTextarea1">
<Form.Label>Details</Form.Label>
<Form.Control
as="textarea"
type="text"
rows="3"
placeholder="How can we help you?"
name="content"
value={this.state.content}
onChange={this.handleInputChange}
required
/>
</Form.Group>
<ReCAPTCHA
className="g-recaptcha"
sitekey="XXXXXXXXXXXXXXXXXXX"
onChange={this.onChange}
theme="dark"
/>
{ this.state.verified ? <p id="error" className="error">{this.state.reply}</p> : null }
{ this.state.showSuccess ? <p id="success" className="success">Thank you, we will be in touch asap.</p> : null }
<Button id="submit" variant="primary" type="submit">
Submit
</Button>
</Form>
</Col>
</Row>
</Container>
</section>
)
}
}
export default Contact
I'm using react-google-recaptcha
(https://www.npmjs.com/package/react-google-recaptcha) for Recaptcha verification and inserted the component top of the submit button:
<ReCAPTCHA
className="g-recaptcha"
sitekey="XXXXXXXXXXXXXXXXXXXXX"
onChange={this.onChange}
theme="dark"
/>
The onChange function should set state.verfied == true
onChange = (value) => {
console.log("Captcha value:", value);
this.setState({
verified: true
})
};
so that this part of handledSubmit()
fires if the reCaptcha was completed and the form gets submitted without page reload:
if (this.state.verified) {
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
.then(this.handleSuccess)
.catch(error => alert(error))
event.preventDefault()
}
otherwise it should render this.state.reply: "Please verify the ReCaptcha."
above the submit button.
The submit button works without completing the reCaptcha and submits the form. It reloads the page to http://localhost:8000/?name=Test&email=test&company=test&content=test&g-recaptcha-response=
I know that my workaround using state probably isn't the correct way of using this module, but the react-google-recaptcha
docs leave no hint on how to correctly integrate the verification with the reCaptcha API.
Happy for any support on this. Thanks!
I needed to change the onChange function to store the reCaptchaResponse like so:
onChange = (result) => {
this.setState({
verified: true,
reCaptchaResponse: result,
})
};
And secondly I updated the condition in handleSubmit to check for verification much earlier and also integrate the reCaptchaResponse in the payload like so:
handleSubmit = event => {
if (this.state.verified) {
const url = 'https://xxxxxxxxxx.execute-api.eu-central-1.amazonaws.com/dev/email/send';
this.setState({
submitting: true
})
const payload = {
name: this.state.name,
email: this.state.email,
company: this.state.company,
content: this.state.content,
result: this.state.reCaptchaResponse
}
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
.then(this.handleSuccess)
.catch(error => alert(error))
event.preventDefault()
} else {
this.setState({
reply: "Please verify the ReCaptcha"
})
}
}