Author avatar

Gaurav Singhal

Formspree AJAX with ES6

Gaurav Singhal

  • Jul 22, 2019
  • 8 Min read
  • 1,547 Views
  • Jul 22, 2019
  • 8 Min read
  • 1,547 Views
Web Development

Introduction

In this guide, we are going to look into Formspree - a service that grants us simple form submission handling. We will see how we can submit the form to Formspree using ES6 syntax in React.

Formspree

When you are building static sites, you will come across numerous challenges surrounding how to deal with dynamic content, or form submissions. Well, perhaps you'd suggest for contact form submission that we can have a "mailto" link in the form action. We can, but that won't be an excellent experience for the user. The users will be required to switch into their email client and then they will also have to hit the send button- that's too much work to contact someone.

Formspree is the best service for static sites that don't have a backend to handle the form submissions. It is useful for portfolio sites and startups that don't want to invest much. Unlike other alternatives, like Google Form, we don't need to sacrifice the look of our website by embedding forms from external sources using an iframe that doesn't fit in with our User Interface (UI) for contact forms. We can make the form on our own that fits well with our site.

Formspree only requires us to have an action attribute that points to their URL. The URL format is https://formspree.io/{your email} and all the forms will be submitted to your email. When the form is submitted for the first time, Formspree will send a confirmation email. Make sure that you confirm by clicking the link in the email to receive form submissions from your website.

Let's Build the Contact Form

1<form action="https://formspree.io/[email protected]" method="POST">
2    <div className="input-group">
3    <label htmlFor="email">E-mail Address</label>
4    <input
5        type="email"
6        name="email"
7        id="email"
8        value={this.state.values.email}
9        onChange={this.handleInputChange}
10        title="Email"
11        required
12    />
13    </div>
14    <div className="input-group">
15    <label htmlFor="message">Message</label>
16    <textarea
17        name="message"
18        id="message"
19        onChange={this.handleInputChange}
20        title="password"
21        required
22    >{this.state.values.message}</textarea>
23    </div>
24    <button type="submit">Send</button>
25</form>
jsx

For sending the form data using AJAX, we will have to add the submit handler and remove the action attribute.

1<form onSubmit={this.submitForm} >
2    ...
3    <button type="submit">Send</button>
4</form>
jsx

Like in my previous guide, Submit Form in React without jQuery AJAX we will have the state and handlers as follows:

1this.state = {
2    values: {
3        email: "",
4        message: ""
5    },
6    isSubmitting: false,
7    isError: false
8};
jsx
1handleInputChange = e =>
2    this.setState({
3      values: { ...this.state.values, [e.target.name]: e.target.value }
4    });
5
6submitForm = e => {
7    e.preventDefault();
8    // fetch() - post data to formspree url
9}
jsx

In my previous guide, we learned how we could submit form data using the fetch() API. For those of you who don't know what that is, it's the new Promise-based native method to make network requests.

1fetch(url, {...options})
2    .then(response => {
3        // resolve the data
4    })
5    .then(data => {
6        // use the data
7    });
javascript

For this guide, we will be using an external library - axios to make the network request for us.

Axios

The problem with fetch is that we require two steps to get the data and make use of it. Suppose, if we have to upload files, fetch won't get us the upload progress. So for such scenarios, we can use Axios.

Internally Axios uses the XML HTTP Request (XHR) and abstracts it's the complex syntax for us and provides a much cleaner method.

Basic Usage

GET Request Example

1axios.get(url, {...options})
2    .then(response => {
3        // handle success
4    })
5    .catch(error => {
6        // handle error
7    })
javascript

POST Request Example

1axios.post(url, data, {...options})
2    .then(response => {
3        // handle success
4    })
5    .catch(error => {
6        // handle error
7    })
javascript

We can also use async/await with Axios:

1const getData = async () => {
2    try {
3        const {data} = await axios.get(url);
4        return data;
5    } catch(err) {
6        console.log(err);
7    }
8}
javascript

submitForm() Handler Using Axios

Now that we know about Axios and how to use its syntax, let's request the Formspree URL.

1submitForm = async e => {
2    e.preventDefault();
3    try {
4        const {data} = await axios.post("https://formspree.io/[email protected]", {...this.state.values});
5    } catch (err) {
6        console.log(err);
7    }
jsx

Complete Code

To summarise all the code above, here's the complete source for this guide.

index.js

1import React, { Component } from "react";
2import ReactDOM from "react-dom";
3
4import axios from "axios";
5
6import "./styles.css";
7
8class ContactForm extends Component {
9  constructor(props) {
10    super(props);
11    this.state = {
12      values: {
13        email: "",
14        message: ""
15      },
16      isSubmitting: false,
17      isError: false
18    };
19  }
20
21  submitForm = async e => {
22    e.preventDefault();
23    console.log(this.state);
24    this.setState({ isSubmitting: true });
25    try {
26        const {data} = await axios.post("https://formspree.io/[email protected]", {...this.state.values});
27    } catch (err) {
28        console.log(err);
29    }
30
31    setTimeout(
32      () =>
33        this.setState({
34          isError: false,
35          message: "",
36          values: { email: "", password: "" }
37        }),
38      1600
39    );
40  };
41
42  handleInputChange = e =>
43    this.setState({
44      values: { ...this.state.values, [e.target.name]: e.target.value }
45    });
46
47  render() {
48    return (
49      <div>
50        <form onSubmit={this.submitForm}>
51          <div className="input-group">
52            <label htmlFor="email">E-mail Address</label>
53            <input
54              type="email"
55              name="email"
56              id="email"
57              value={this.state.values.email}
58              onChange={this.handleInputChange}
59              title="Email"
60              required
61            />
62          </div>
63          <div className="input-group">
64            <label htmlFor="message">Message</label>
65            <textarea
66              name="message"
67              id="message"
68              onChange={this.handleInputChange}
69              title="password"
70              required
71            >{this.state.values.message}</textarea>
72          </div>
73          <button type="submit">Send</button>
74        </form>
75        <div className={`message ${this.state.isError && "error"}`}>
76          {this.state.isSubmitting ? "Submitting..." : this.state.message}
77        </div>
78      </div>
79    );
80  }
81}
82
83function App() {
84  return (
85    <div className="App">
86      <h1>Contact US</h1>
87      <ContactForm />
88    </div>
89  );
90}
91
92const rootElement = document.getElementById("root");
93ReactDOM.render(<App />, rootElement);
jsx

styles.css

1.App {
2  font-family: sans-serif;
3}
4.input-group {
5  margin-bottom: 10px;
6}
7.input-group label {
8  display: block;
9  margin-bottom: 5px;
10}
11button {
12  border: none;
13  padding: 8px 24px;
14}
15.message {
16  margin-top: 20px;
17  font-weight: 600;
18}
19.message.error {
20  color: red;
21}
css

Limitations

Unfortunately, Formspree doesn't allow AJAX calls to their URL and access to their API for free users. So, those users will have to make do with the action form attribute.

That's it from this guide. Until next time, keep hustling and code like a beast.

References