- Published on
How to connect GatsbyJS with Netlify forms.
- Authors
- Name
- Adam Piskorek
- @hvitis_
Explaining how to make your Serverless Functions Integration works!
Introduction
Let's start by explaining things a bit. GatsbyJS is blazing fast. Maybe you've seen that when you've entered this site. Why? For many reasons but one of them is that it generates a Static Site. You are now reading a post on such a site.
What is a static site?
It's a site that is prebuild, already made, packed, awaiting to be send to client with a first request. It's not build when user makes a request to the server.
What's a dynamic site?
Imagine you click on link to a forum page.
- After clicking request is being send to the server.
- Server collects all new posts and data generated by users.
- This data is combined with JS, CSS and HTML and delivered to your browser.
Each time you click the website can be different because it changes depending on other users' input. Even if it's a Django blog with only you as a user - the mechanism is the same.
Then how can I have a blog on Static Site? Simply by not having a database with posts. All the posts I've written are being shipped to you. There are no additional data packages with blog content when you surf my page. All the data is in your browser already.
So how can you write me a message or comment this post? Well, in your browser, right now (for example if you open Developer Tools) there is JavaScript code that can send your data to specific routes. Those routes lead to Netlify which are places with servers and databases. Those servers are thousands of miles away from you so each time you want to write a comment or send me a message you need to make a request. That's why it takes seconds or minutes from the moment you send to the moment I recieve a notification. That's why you can switch off your internet and continue navigating to different posts - all the data is in your browser already!
How to make Netlify forms work with Formik?
All the contrary information on the internet make it so confusing when it's so simple. In order to make them work, the simplest thing you need is this:
(That is TypeScript file so *.TSX):
const SomeForm: React.SFC<{}> = () => {
return (
<Formik
initialValues={
"form-name": "Contact Me Form",
someInputField: ""}
render={({ }: FormikProps<MyFormValues>) => (
<Form name="Contact Me Form" method="post" data-netlify="true">
<input
type="hidden"
name="form-name"
value="Contact Me Form" />
<input
type="text"
name="someInputField"
/>
<button title="Submit" type="submit" />
</Form>
)}
/>
)
}
Explanation:
This is stripped code that has data neccessary for Netlify forms to work. To see complete code scroll down, but let's start explaining.
First Formik component with initialValues. You need "form-name" that's value will correspond with Form's name and input's value.
<Formik initialValues={ "form-name": "Contact Me Form", someInputField: ""}
Secondly you need form with name corresponding to form-name on Formik and to value on hidden input. Also you need to enable Netlify bot here by data-netlify="true".
<form name="Contact Me Form" method="post" data-netlify="true"></form>
Create hidden input that will allow netlify's bot connect your form's data with Formik values that are sent onSubmit.
<input type="hidden" name="form-name" value="Contact Me Form" />
And finally the last step is sending the data to a root URL. You can do that with onSubmit function:
<Formik
initialValues={
"form-name": "Contact Me Form",
someInputField: ""}
}
onSubmit={(
values: MyFormValues,
) => {
fetch("/", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: encode({
"form-name": "formik",
...values,
}),
})
.then(succ => console.log(succ))
.catch(error => console.log(error))
}}
(this is incomplete! for full code scroll down.)
- In order to send the form correctly you need to include Encoding!
function encode(data) {
return Object.keys(data)
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
.join('&')
}
This is the key to make Netlify forms work. Once you do that and deploy, you will be able to use that form (it doesn't work locally!).
There is more options like reCatcha, or filtering SPAM that netlify provides. You don't need form's action or honeypots to make sending forms possible.
Extra options:
Filtering spam:
Add "bot-field": "", to initial values
<Formik initialValues={{"bot-field": "", "form-name": "Contact Me Form",
someInputField: ""}}
and add data-netlify-honeypot="bot-field" to Form
<form
name="Contact Me Form"
method="post"
data-netlify="true"
data-netlify-honeypot="bot-field"
></form>
Redirect after successful submission:
- Import navigate from Gatsby
import { navigate } from 'gatsby'
- Add onSubmit function
- Make a new "thanks for contacting me" page (Optional, you can redirect to any page.)
<Formik
initialValues={
"form-name": "Contact Me Form",
someInputField: ""}
}
onSubmit={(
values: MyFormValues,
) => {
fetch("/", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: encode({
"form-name": "formik",
...values,
}),
})
.then(succ => navigate("/thanks"))
.catch(error => alert(error))
}}
Full code:
import * as React from 'react'
import { Formik, FormikProps, Form } from 'formik'
import { navigate } from 'gatsby'
interface FormValidValues {
message: string
}
function encode(data) {
return Object.keys(data)
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
.join('&')
}
const Contact: React.SFC<{}> = () => {
return (
<Formik
initialValues={{
'bot-field': '',
'form-name': 'contact',
message: '',
}}
onSubmit={(values: MyFormValues) => {
fetch('/', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: encode({
'form-name': 'formik',
...values,
}),
})
.then((succ) => navigate('/thanks'))
.catch((error) => console.log(error))
}}
render={({ handleChange, values }: FormikProps<FormValidValues>) => (
<Form
name="contact"
method="post"
data-netlify-honeypot="bot-field"
data-netlify="true"
>
<Input type="hidden" name="form-name" value="contact" />
<Input
type="text"
name="message"
value={`${values.firstName}`}
onChange={handleChange}
label="Name"
/>
<Button title="Submit" type="submit" />
</Form>
)}
/>
)
}
export default Contact
Did you make any mistakes when using REACT or you've seen one here? Tell me about your insights. Leave a comment with You are most welcome to see more posts of this type just go to home page