Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React component #336

Closed
angelod1as opened this issue Jul 28, 2019 · 7 comments
Closed

React component #336

angelod1as opened this issue Jul 28, 2019 · 7 comments

Comments

@angelod1as
Copy link

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
@mckennapsean
Copy link
Collaborator

Thanks for sharing this!

@mckennapsean
Copy link
Collaborator

Was there a question or suggestion with this particular issue? Or did it work for you?

@angelod1as
Copy link
Author

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.

@mckennapsean
Copy link
Collaborator

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 :)

@angelod1as
Copy link
Author

Oh, nice. Feel free to share it, it's kinda a way of 'giving back to the community'

@mckennapsean
Copy link
Collaborator

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!

@angelod1as
Copy link
Author

angelod1as commented Jan 25, 2021

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>
      )}
    </>
  )
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants