I'm kinda new to github so I don't know if this is the correct way to suggest this.
I've written a working React Component (without any styles, as the dev chose pure css and I'll style with styled components).
It works as intended, with controlled forms, conditional Thanks component and all that React can offer.
import React, { Component } from 'react'
const config = {
script:
'https://script.google.com/macros/s/AKfycbwMxYDrufp73bKdU8gMvxFDdHRuzcR4IKQUB33B7GqwyfyZS04/exec',
sheet: 'responses',
// email: '',
}
const Thanks = () => (
<div className="thankyou_message">
<h2>Thanks for contacting us! We will get back to you soon!</h2>
</div>
)
class Form extends Component {
constructor(props) {
super(props)
this.state = {
form: {
name: '',
message: '',
email: '',
honeypot: '',
},
sent: false,
clicked: false,
}
this.handleChange = this.handleChange.bind(this)
this.handleClick = this.handleClick.bind(this)
}
handleClick = () => {
const { form } = this.state
// loading
this.setState({ clicked: true })
// sent
const setSent = () => {
this.setState({ sent: true })
}
// checking if bot
const { honeypot } = form
if (honeypot) {
return false
}
// sending through xhr as axios won't work (CORS)
const xhr = new XMLHttpRequest()
xhr.open('POST', config.script)
// xhr.withCredentials = true
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.onreadystatechange = function xhrGo() {
setSent()
}
const encoded = Object.keys(form)
.map(k => {
return `${encodeURIComponent(k)}=${encodeURIComponent(form[k])}`
})
.join('&')
// finally sending
xhr.send(encoded)
return true
}
handleChange = ({ target }) => {
const { id, value } = target
const { state } = this
state.form[id] = value
this.setState(state)
}
render() {
const {
form: { name, message, email, honeypot },
sent,
clicked,
} = this.state
return (
<>
{sent ? (
<Thanks />
) : (
<>
<form
// method="POST"
// action={config.script} // change this url
>
<div>
<fieldset>
<label htmlFor="name">
Name:
<input
onChange={this.handleChange}
id="name"
key="name"
name="name"
placeholder="What your Mom calls you"
value={name}
/>
</label>
</fieldset>
<fieldset>
<label htmlFor="message">
Message:
<textarea
onChange={this.handleChange}
id="message"
key="message"
name="message"
rows={10}
placeholder="Tell us what's on your mind..."
value={message}
/>
</label>
</fieldset>
<fieldset>
<label htmlFor="email">
Your Email Address:
<input
onChange={this.handleChange}
id="email"
key="email"
name="email"
type="email"
required
placeholder="[email protected]"
value={email}
/>
</label>
</fieldset>
<fieldset className="honeypot-field" style={{ display: 'none' }}>
<label htmlFor="honeypot">
{/* To help avoid spam, utilize a Honeypot technique with a hidden text field; must
be empty to submit the form! Otherwise, we assume the user is a spam bot. */}
<input
onChange={this.handleChange}
id="honeypot"
key="honeypot"
type="text"
name="honeypot"
value={honeypot}
/>
</label>
</fieldset>
{clicked ? (
<button type="button" disabled>
Loading
</button>
) : (
<button type="button" onClick={() => this.handleClick()}>
Send
</button>
)}
</div>
</form>
</>
)}
</>
)
}
}
export default Form
Thanks for sharing this!
Was there a question or suggestion with this particular issue? Or did it work for you?
This is actually a suggestion. I didn't know where exactly I could put this code and maybe make it available for everyone so I opened this issue. Sorry, kinda new to this "contributing" stuff.
Awesome, this is a great place to share that actually - thanks again for doing that! Just wanted to make sure I didn't miss anything :)
Oh, nice. Feel free to share it, it's kinda a way of 'giving back to the community'
Thanks @angelod1as ! This is a great way to share it, if anyone wants to see this in the main readme, we could add links or references to the FAQ section perhaps. I've seen similar requests before, so definitely something we'll consider if people keep asking for it, too. Thanks again for sharing!
I just updated this form using hooks and React Hook Form. It's below, for comparison and later usage,
import { useCallback, useState } from 'react'
import { useForm } from 'react-hook-form'
const config = {
script:
'https://script.google.com/macros/s/AKfycbwMxYDrufp73bKdU8gMvxFDdHRuzcR4IKQUB33B7GqwyfyZS04/exec',
sheet: 'responses',
// email: '',
}
export default function Contact() {
const { register, handleSubmit } = useForm()
const [sent, setSent] = useState(false)
const onSubmit = useCallback((data) => {
const { honeypot } = data
// checking if bot
if (honeypot) {
return false
}
// use xhr as axios won't work (CORS)
const xhr = new XMLHttpRequest()
xhr.open('POST', config.script)
// xhr.withCredentials = true
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.onreadystatechange = function xhrGo() {
setSent(true)
}
// preparing data
const encoded = Object.keys(data)
.map(k => {
return `${encodeURIComponent(k)}=${encodeURIComponent(data[k])}`
})
.join('&')
// finally sending
xhr.send(encoded)
return true
}, [])
return (
<>
{sent ? (
<div className="thankyou_message">
<h2>Thanks for contacting us! We will get back to you soon!</h2>
</div>
) : (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="name">
Name:
<input
ref={register}
id="name"
key="name"
name="name"
placeholder="What your Mom calls you"
/>
</label>
<label htmlFor="message">
Message:
<textarea
ref={register}
id="message"
key="message"
name="message"
rows={10}
placeholder="Tell us what's on your mind..."
/>
</label>
<label htmlFor="email">
Your Email Address:
<input
ref={register}
id="email"
key="email"
name="email"
type="email"
required
placeholder="[email protected]"
/>
</label>
<label htmlFor="honeypot" style={{ display: 'none' }}>
{/* To help avoid spam, utilize a Honeypot technique with a hidden text field; must
be empty to submit the form! Otherwise, we assume the user is a spam bot. */}
<input
ref={register}
id="honeypot"
key="honeypot"
type="text"
name="honeypot"
/>
</label>
<input type="submit" />
</div>
</form>
)}
</>
)
}
Most helpful comment
Oh, nice. Feel free to share it, it's kinda a way of 'giving back to the community'