← All guides

Gatsby

React Forms with Gatsby

Gatsby sites are React apps that render to static HTML. A controlled React component with a fetch call lets you collect submissions without leaving the page, fully compatible with Gatsby's static export and CDN deployment.

  1. 01Create your form in Formward

    Sign up at formward.eu, create a new form, and copy the endpoint URL (https://formward.eu/f/your-form-id).

  2. 02Create a ContactForm component

    Add a new file src/components/ContactForm.jsx (or .tsx) and paste the component below. It uses controlled inputs and submits via fetch with Accept: application/json so Formward returns a JSON response instead of a redirect.

    // src/components/ContactForm.jsx
    import React, { useState } from 'react';
    
    export default function ContactForm() {
      const [fields, setFields] = useState({ name: '', email: '', message: '' });
      const [status, setStatus] = useState('idle'); // idle | submitting | success | error
    
      function handleChange(e) {
        setFields({ ...fields, [e.target.name]: e.target.value });
      }
    
      async function handleSubmit(e) {
        e.preventDefault();
        setStatus('submitting');
    
        try {
          const res = await fetch('https://formward.eu/f/your-form-id', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
              Accept: 'application/json',
            },
            body: new URLSearchParams({ ...fields, _gotcha: '' }).toString(),
          });
    
          if (!res.ok) throw new Error('Network response was not ok');
          setStatus('success');
          setFields({ name: '', email: '', message: '' });
        } catch {
          setStatus('error');
        }
      }
    
      if (status === 'success') {
        return <p>Thank you, your message has been sent!</p>;
      }
    
      return (
        <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 14, maxWidth: 480 }}>
          <label>
            Name
            <input type="text" name="name" value={fields.name} onChange={handleChange} required
              style={{ display: 'block', width: '100%', padding: '8px 12px', border: '1px solid #ccc', borderRadius: 4, fontSize: '1rem', marginTop: 4 }} />
          </label>
          <label>
            Email
            <input type="email" name="email" value={fields.email} onChange={handleChange} required
              style={{ display: 'block', width: '100%', padding: '8px 12px', border: '1px solid #ccc', borderRadius: 4, fontSize: '1rem', marginTop: 4 }} />
          </label>
          <label>
            Message
            <textarea name="message" value={fields.message} onChange={handleChange} rows={5} required
              style={{ display: 'block', width: '100%', padding: '8px 12px', border: '1px solid #ccc', borderRadius: 4, fontSize: '1rem', marginTop: 4, resize: 'vertical' }} />
          </label>
          {/* honeypot: keep hidden */}
          <input type="text" name="_gotcha" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" />
          <button type="submit" disabled={status === 'submitting'}
            style={{ alignSelf: 'flex-start', padding: '10px 24px', background: '#000', color: '#fff', border: 'none', borderRadius: 4, fontSize: '1rem', cursor: 'pointer' }}>
            {status === 'submitting' ? 'Sending…' : 'Send'}
          </button>
          {status === 'error' && <p style={{ color: 'red' }}>Something went wrong. Please try again.</p>}
        </form>
      );
    }
  3. 03Use the component on a page

    Import and render ContactForm on any Gatsby page, for example src/pages/contact.jsx. Gatsby will include the component in the static HTML it generates, and the fetch call runs in the browser at runtime.

    // src/pages/contact.jsx
    import React from 'react';
    import ContactForm from '../components/ContactForm';
    
    export default function ContactPage() {
      return (
        <main>
          <h1>Contact</h1>
          <ContactForm />
        </main>
      );
    }
  4. 04Test and view submissions

    Run gatsby develop, open http://localhost:8000/contact, and submit the form. The component shows a success message without a page reload. Check the Formward dashboard to confirm the submission arrived.

Ready to collect your first submission?

Create your form
React Forms with Gatsby | Formward