React Components
Overview
React components and hooks for building forms with Formr. Provides pre-built components and hooks that handle form submission, validation, and error handling.
Installation
npm install formr-ui
# or
pnpm add formr-ui
# or
yarn add formr-uiRequires React 18+
Quick Start
import { useFormr, Form, Field, Errors } from 'formr-ui';
export default function ContactForm() {
const { submit, errors, pending } = useFormr({
formId: 'contact',
apiKey: process.env.NEXT_PUBLIC_FORMR_KEY,
});
return (
<Form onSubmit={submit}>
<Field
name="email"
type="email"
label="Email"
required
/>
{errors.email && <Errors field="email" message={errors.email} />}
<Field
name="message"
type="textarea"
label="Message"
required
/>
<button disabled={pending}>
{pending ? 'Submitting...' : 'Send'}
</button>
{errors._form && <Errors message={errors._form} />}
</Form>
);
}Using Hooks Directly
import { useFormr } from 'formr-ui/hooks';Components
<Form>
<Form>Wrapper component that handles form submission.
Props:
onSubmit- Submit handler functionAll standard HTML form props supported
Example:
<Form onSubmit={submit}>
{/* form fields */}
</Form><Field>
<Field>Input field component.
Props:
name- Field name (required)label- Field labeltype- Input type (text, email, number, textarea, etc.)All standard HTML input props supported
Example:
<Field
name="email"
type="email"
label="Email Address"
required
placeholder="you@example.com"
/><Errors>
<Errors>Error display component.
Props:
field- Field name to display errors formessage- Error message to displayerrors- Error object from useFormr
Example:
{errors.email && <Errors field="email" message={errors.email} />}
{errors._form && <Errors message={errors._form} />}Hook: useFormr(options)
useFormr(options)React hook for form management.
Options
formId- Form ID (required)apiKey- API key (optional)baseUrl- Base URL (optional)sessionId- Session ID (optional)
Returns
submit(data)- Submit functionerrors- Error objectpending- Loading statereset()- Reset errors and pending state
Example
const { submit, errors, pending, reset } = useFormr({
formId: 'contact-form',
apiKey: process.env.NEXT_PUBLIC_FORMR_KEY,
});Plain HTML Enhancement
Add the browser script to any HTML form:
<form method="post" action="https://api.formr.dev/submit" data-formr="contact">
<input name="email" type="email" required />
<input name="message" type="text" required />
<button>Send</button>
</form>
<script async src="https://cdn.formr.dev/v1/browser.min.js"></script>The script will:
Intercept form submissions
Validate client-side (optional, UX only)
Submit via Formr API
Handle success/error states
Examples
Basic Form
import { useFormr, Form, Field, Errors } from 'formr-ui';
export default function ContactForm() {
const { submit, errors, pending } = useFormr({
formId: 'contact-form',
});
return (
<Form onSubmit={submit}>
<Field name="email" type="email" label="Email" required />
{errors.email && <Errors field="email" />}
<Field name="message" type="textarea" label="Message" required />
<button disabled={pending}>
{pending ? 'Submitting...' : 'Send'}
</button>
</Form>
);
}Custom Styled Form
import { useFormr, Form, Field, Errors } from 'formr-ui';
export default function StyledContactForm() {
const { submit, errors, pending } = useFormr({
formId: 'contact-form',
});
return (
<Form onSubmit={submit} className="max-w-md mx-auto">
<div className="mb-4">
<Field
name="email"
type="email"
label="Email"
required
className="w-full p-2 border rounded"
/>
{errors.email && (
<Errors field="email" className="text-red-500 text-sm mt-1" />
)}
</div>
<div className="mb-4">
<Field
name="message"
type="textarea"
label="Message"
required
className="w-full p-2 border rounded"
/>
</div>
<button
disabled={pending}
className="bg-blue-500 text-white px-4 py-2 rounded disabled:opacity-50"
>
{pending ? 'Submitting...' : 'Send'}
</button>
</Form>
);
}Using Hook Without Components
import { useFormr } from 'formr-ui/hooks';
export default function CustomForm() {
const { submit, errors, pending } = useFormr({
formId: 'contact-form',
});
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const answers = Object.fromEntries(formData);
await submit({ answers });
};
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" required />
{errors.email && <div className="error">{errors.email}</div>}
<button disabled={pending}>Submit</button>
</form>
);
}Features
✅ Light Client-side Validation: Required/min/max/pattern/enum for instant UX
✅ Server Validates Everything: Client checks are advisory, server is authoritative
✅ Unstyled Primitives: Bring your own styles
✅ TypeScript Support: Full TypeScript definitions
✅ Tree-shakeable: Only import what you need
Next Steps
Development Tools - Other development tools
SDK Guide - JavaScript/TypeScript SDK
API Reference - Complete API documentation
Last updated