react-netlify-forms

Formik newsletter example

In this example we will create a simple newsletter signup form with Formik. It only includes an email field which is validated client-side (note: client-side validation is not safe, thus you might see data other than emails in Netlify).

In order to use Formik's handlers, we use a hook-based approach which allows us to link Formik's submit handler with react-netlify-forms one. Therefore, we have to import

useNetlifyForm
and
useFormik
. Furthermore, we have to use
NetlifyFormProvider
and
NetlifyFormComponent
to render the form with context ourselves:

import {
useNetlifyForm,
NetlifyFormProvider,
NetlifyFormComponent,
Honeypot
} from 'react-netlify-forms'
import { useFormik } from 'formik'

First, we get all Netlify Forms functions through

useNetlifyForm
and then setup Formik with
useFormik
. We supply the former submit handler to Formik's
onSubmit
to link them which means that the form is validated by Formik and then values are sent to the server by react-netlify-forms.

NetlifyFormProvider
enables us to create the corresponding context by passing Netlify functions through props. In the following, the context is consumed by
NetlifyFormComponent
to render a form with all neccessary attributes.

Instead of managing form state through react-netlify-forms, it is now controlled by Formik with e.g.

handleChange
.

Last but not least, note that we defined validation logic in Formik as a simple check whether input is filled and it matches a regular expression describing emails.

See the full example in action here:

function NewsletterForm() {
const netlify = useNetlifyForm({
name: 'Formik',
action: '/thanks',
honeypotName: 'bot-field',
onSuccess: (response, context) => {
console.log('Successfully sent form data to Netlify Server')
}
})
const {
handleSubmit,
handleChange,
handleBlur,
touched,
errors,
values
} = useFormik({
initialValues: { email: '' },
onSubmit: (values) => netlify.handleSubmit(null, values),
validate: (values) => {
const errors = {}
if (!values.email) {
errors.email = 'Email is required'
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
) {
errors.email = 'Invalid email address'
}
return errors
}
})
return (
<NetlifyFormProvider {...netlify}>
<NetlifyFormComponent onSubmit={handleSubmit}>
<Honeypot />
{netlify.success && (
<p sx={{ variant: 'alerts.success', p: 3 }}>
Thanks for contacting us!
</p>
)}
{netlify.error && (
<p sx={{ variant: 'alerts.muted', p: 3 }}>
Sorry, we could not reach servers. Because it only works on Netlify,
our GitHub demo does not provide a response.
</p>
)}
<div>
<label htmlFor='email' sx={{ variant: 'forms.label' }}>
Email:
</label>
<input
type='email'
name='email'
id='email'
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
sx={{
variant: 'forms.input'
}}
/>
{touched.email && errors.email ? (
<div sx={{ variant: 'text.error' }}>{errors.email}</div>
) : null}
</div>
<div sx={{ pt: 3 }}>
<button type='submit' sx={{ variant: 'buttons.success' }}>
Submit
</button>
<button type='reset' sx={{ variant: 'buttons.danger' }}>
Reset
</button>
</div>
</NetlifyFormComponent>
</NetlifyFormProvider>
)
}
© 2023 Björn Clees, made with ❤ using Gatsby