fetch and FormData. No React-specific package is required.
Contact Form
import { useState } from 'react';
const FORMBNB_ENDPOINT = 'https://api.formbnb.com/f/YOUR_ORG/YOUR_FORM';
export function ContactForm() {
const [status, setStatus] = useState<'idle' | 'sending' | 'success' | 'error'>('idle');
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
if (status === 'sending') return;
setStatus('sending');
const form = event.currentTarget;
const formData = new FormData(form);
try {
const response = await fetch(FORMBNB_ENDPOINT, {
method: 'POST',
body: formData,
headers: { Accept: 'application/json' },
});
if (!response.ok) throw new Error('Submission failed');
form.reset();
setStatus('success');
} catch {
setStatus('error');
}
}
return (
<form onSubmit={handleSubmit}>
<input type="text" name="name" placeholder="Name" required />
<input type="email" name="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<button type="submit" disabled={status === 'sending'}>
{status === 'sending' ? 'Sending...' : 'Send'}
</button>
{status === 'success' && <p>Thanks. Your message was sent.</p>}
{status === 'error' && <p>Something went wrong. Please try again.</p>}
</form>
);
}
With React Hook Form
import { useForm } from 'react-hook-form';
type ContactFields = {
name: string;
email: string;
message: string;
};
export function ContactForm() {
const { register, handleSubmit, reset, formState } = useForm<ContactFields>();
async function onSubmit(data: ContactFields) {
const response = await fetch('https://api.formbnb.com/f/YOUR_ORG/YOUR_FORM', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Submission failed');
reset();
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name', { required: true })} placeholder="Name" />
<input {...register('email', { required: true })} type="email" placeholder="Email" />
<textarea {...register('message', { required: true })} placeholder="Message" />
<button type="submit" disabled={formState.isSubmitting}>
{formState.isSubmitting ? 'Sending...' : 'Send'}
</button>
</form>
);
}
File Uploads
export function ApplicationForm() {
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
const response = await fetch('https://api.formbnb.com/f/YOUR_ORG/apply', {
method: 'POST',
body: new FormData(event.currentTarget),
headers: { Accept: 'application/json' },
});
if (!response.ok) throw new Error('Submission failed');
}
return (
<form onSubmit={handleSubmit} encType="multipart/form-data">
<input name="email" type="email" required />
<input name="resume" type="file" />
<button type="submit">Apply</button>
</form>
);
}