Installation
Install the official React library:Copy
npm install @spike-forms/react
Using the Hook
TheuseForm hook provides everything you need:
Copy
import { useForm } from '@spike-forms/react';
function ContactForm() {
const { state, handleSubmit, reset } = useForm('YOUR_FORM_SLUG');
if (state.succeeded) {
return (
<div>
<p>Thanks for your message!</p>
<button onClick={reset}>Send another</button>
</div>
);
}
return (
<form onSubmit={handleSubmit}>
<input type="email" name="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<button type="submit" disabled={state.submitting}>
{state.submitting ? 'Sending...' : 'Send'}
</button>
{state.errors && <p className="error">{state.errors}</p>}
</form>
);
}
Using the Component
For simpler cases, use theSpikeForm component:
Copy
import { SpikeForm, ValidationError } from '@spike-forms/react';
function ContactForm() {
return (
<SpikeForm formSlug="YOUR_FORM_SLUG">
<input type="email" name="email" placeholder="Email" required />
<ValidationError field="email" />
<textarea name="message" placeholder="Message" required />
<ValidationError field="message" />
<button type="submit">Send</button>
</SpikeForm>
);
}
Without the Library
You can also use Spike with plain fetch:Copy
import { useState } from 'react';
function ContactForm() {
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setStatus('loading');
const form = e.currentTarget;
const data = new FormData(form);
try {
const response = await fetch('https://spike.ac/api/f/YOUR_FORM_SLUG', {
method: 'POST',
body: data,
headers: { 'Accept': 'application/json' }
});
if (response.ok) {
setStatus('success');
form.reset();
} else {
setStatus('error');
}
} catch {
setStatus('error');
}
}
if (status === 'success') {
return <p>Thanks for your message!</p>;
}
return (
<form onSubmit={handleSubmit}>
<input type="email" name="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<button type="submit" disabled={status === 'loading'}>
{status === 'loading' ? 'Sending...' : 'Send'}
</button>
{status === 'error' && <p>Something went wrong.</p>}
</form>
);
}
With React Hook Form
Copy
import { useForm } from 'react-hook-form';
type FormData = {
email: string;
message: string;
};
function ContactForm() {
const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<FormData>();
async function onSubmit(data: FormData) {
const response = await fetch('https://spike.ac/api/f/YOUR_FORM_SLUG', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (response.ok) {
alert('Message sent!');
}
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="email"
{...register('email', { required: 'Email is required' })}
/>
{errors.email && <span>{errors.email.message}</span>}
<textarea
{...register('message', { required: 'Message is required' })}
/>
{errors.message && <span>{errors.message.message}</span>}
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Sending...' : 'Send'}
</button>
</form>
);
}
TypeScript Support
The library is fully typed:Copy
import { useForm, FormState } from '@spike-forms/react';
interface ContactFormData {
email: string;
message: string;
phone?: string;
}
function ContactForm() {
const { state, handleSubmit } = useForm<ContactFormData>('YOUR_FORM_SLUG');
// state is typed as FormState<ContactFormData>
}