1

I am trying to use a lambda function to sent contact form submissions to an email. The site is built on React, the lambda was built following the guide they suggest Building a serverless contact form with AWS Lambda and AWS SES

However, the issue is that in the guide he uses vanilla JS instead of something more suitable for React and I can't figure out where to place the JS code or if I need to do something else to make it work.

The lambda function work and I can send emails using a curl command such as

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"email":"john.doe@email.com","name":"John Doe","content":"Hey!"}' \
  https://{id}.execute-api.{region}.amazonaws.com/{stage}/email/send

But it does not function on the form directly because the function is expecting a header "Content-Type: application/json" so I need to add this snippet of JS code, but I don't know where and the site is failing because of that.

const form = document.getElementById('contactForm')
const url = 'https://{id}.execute-api.{region}.amazonaws.com/{stage}/email/send'
const toast = document.getElementById('toast')
const submit = document.getElementById('submit')

function post(url, body, callback) {
  var req = new XMLHttpRequest();
  req.open("POST", url, true);
  req.setRequestHeader("Content-Type", "application/json");
  req.addEventListener("load", function () {
    if (req.status < 400) {
      callback(null, JSON.parse(req.responseText));
    } else {
      callback(new Error("Request failed: " + req.statusText));
    }
  });
  req.send(JSON.stringify(body));
}
function success () {
  toast.innerHTML = 'Thanks for sending me a message! I\'ll get in touch with you ASAP. :)'
  submit.disabled = false
  submit.blur()
  form.name.focus()
  form.name.value = ''
  form.email.value = ''
  form.content.value = ''
}
function error (err) {
  toast.innerHTML = 'There was an error with sending your message, hold up until I fix it. Thanks for waiting.'
  submit.disabled = false
  console.log(err)
}

form.addEventListener('submit', function (e) {
  e.preventDefault()
  toast.innerHTML = 'Sending'
  submit.disabled = true

  const payload = {
    name: form.name.value,
    email: form.email.value,
    content: form.content.value
  }
  post(url, payload, function (err, res) {
    if (err) { return error(err) }
    success()
  })
})
<form id="contactForm">
  <input type="text" name="name" required placeholder="Your name" />
  <input type="email" name="email" required placeholder="Your email address" />
  <input type="text" name="phone_number" required placeholder="Your phone number" />
  <textarea name="message" required placeholder="Write your message..." >
  </textarea>
  <button id="submit" type="submit">Send
    <i className="flaticon-tick"></i> 
  </button>
</form>

And the form is located inside a react functional component:

const ContactForm = () => {
    return (
        <form>
            <!-- Above form is here -->
        </form>
    )
}
export default ContactForm

I am trying to imbed it directly into the component but it seems like that is not working. Where should this JS code be within my React project?

I am not sure if I need to use something like a hook in React. (I am pretty now to react and don't really understand how all that works yet)

This is the repository:Deep-Blue

and the site is located at deep-blue.io

I also asked the Gatsby community and did not get an answer, I have been looking at many different tutorials like, this one but they all either use different technologies or fall short of explaining how to handle form submissions in ReactJS with GastbyJS

Chris
  • 704
  • 1
  • 11
  • 32

2 Answers2

1

Opened a PR.
There you can see form that submits data in uncontrolled manner like you had it before, only states for button and toast were added.
I don't think you really need a controlled state for such a simple form, but you will totally need it in most react apps so read about it here and here.

import React, {useState} from 'react'
import {StaticImage} from 'gatsby-plugin-image'

const url = 'https://ob402y9vji.execute-api.eu-central-1.amazonaws.com/dev/email/send'

const ContactForm = () => {
    const [toastText, setToastText] = useState('')
    const [disabled, setDisabled] = useState(false)

    const onSuccess = (form) => {
        setToastText('Thanks for sending me a message! I\'ll get in touch with you ASAP. :)')
        setDisabled(false)
        form.name.focus()
        form.name.value = ''
        form.email.value = ''
        form.phone_number.value = ''
        form.message.value = ''
    }

    const onError = (err) => {
        setToastText('There was an error with sending your message, hold up until I fix it. Thanks for waiting.')
        setDisabled(false)
        console.log(err)
    }

    const onSubmit = (e) => {
        e.preventDefault()
        setToastText('Sending')
        setDisabled(true)

        const form = e.target;
        const payload = {
            name: form.name.value,
            email: form.email.value,
            content: form.message.value,
            phone_number: form.phone_number.value
        }

        post(url, payload, function (err) {
            if (err) {
                return onError(err)
            }
            onSuccess(form)
        })
    }

    return (
        <section className="contact-area pb-100">
            <div className="container">
                <div className="section-title">
                    <span className="sub-title">
                        <StaticImage
                            src='../../assets/images/star-icon.png'
                            alt=""
                            placeholder="tracedSVG"
                        />
                        Get in Touch
                    </span>
                    <h2>Ready to Get Started?</h2>
                    <p>Make an appointment for a free consultation.</p>
                </div>

                <div className="row">
                    <div className="col-lg-6 col-md-12">
                        <div className="contact-image">
                            <StaticImage
                                src='../../assets/images/contact.png'
                                alt="person at a help desk ready to be contacted"
                                placeholder="tracedSVG"
                            />
                        </div>
                    </div>

                    <div className="col-lg-6 col-md-12">
                        <div className="contact-form">
                            <form id="contactForm" onSubmit={onSubmit}>
                                <div className="row">
                                    <div className="col-lg-12 col-md-6">
                                        <div className="form-group">
                                            <input
                                                name="name"
                                                type="text"
                                                className="form-control"
                                                required
                                                placeholder="Your name"
                                            />
                                        </div>
                                    </div>

                                    <div className="col-lg-12 col-md-6">
                                        <div className="form-group">
                                            <input
                                                name="email"
                                                type="email"
                                                className="form-control"
                                                required
                                                placeholder="Your email address"
                                            />
                                        </div>
                                    </div>

                                    <div className="col-lg-12 col-md-12">
                                        <div className="form-group">
                                            <input
                                                name="phone_number"
                                                type="text"
                                                className="form-control"
                                                required
                                                placeholder="Your phone number"
                                            />
                                        </div>
                                    </div>

                                    <div className="col-lg-12 col-md-12">
                                        <div className="form-group">
                                            <textarea
                                                name="message"
                                                className="form-control"
                                                cols="30"
                                                rows="6"
                                                required
                                                placeholder="Write your message..."
                                            />
                                        </div>
                                    </div>

                                    <div>{toastText}</div>

                                    <div className="col-lg-12 col-md-12">
                                        <button id="submit" type="submit" className="default-btn" disabled={disabled}>
                                            <i className="flaticon-tick"></i>
                                            Send Message <span></span>
                                        </button>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    )

}

nickbullock
  • 6,424
  • 9
  • 27
  • I tested the code last night and there is still and issue with the response and changing the 'sending' message to an error or success message. Its probably related to the addEventListener but i'm not sure what I would have to do fix that. Any advice? Thank you so so very much – Chris Jul 01 '21 at 12:10
  • ok, show me the error. I guess it was a CORS error because your AWS server policy restricted any requests from localhost, I saw that as well. so probably when you will push this to production it will work. – nickbullock Jul 01 '21 at 12:18
  • It’s not an error as such. It the message gets sent and arrives in my mailbox but it does change the ‘sending’ message to a success message. I posted the server response on the pull request comment. – Chris Jul 01 '21 at 12:22
  • You are correct it is a CORS error. Working on fixing it now – Chris Jul 01 '21 at 13:43
0

Instead of pulling code from Javascript to react, I think you should give a try to amplify-react package which will give you a better control over your contact form. Below is a step by step guide for Amplify-react

https://docs.amplify.aws/start/getting-started/installation/q/integration/react

Mahesh
  • 1,427
  • 2
  • 19
  • 42