useSnipForm
import { useSnipForm } from '@snipform/react';import type { Fields } from '@snipform/react';
const fields: Fields = { email: { type: 'email', rules: { required: 'Email is required', email: null } }, plan: { type: 'select', initial: 'starter' },};
const form = useSnipForm({ key: 'YOUR_FORM_KEY', fields });The hook returns a SnipFormHandle. Call it once per form, at the top of the component that renders it.
Options
Section titled “Options”| Option | Type | Default | |
|---|---|---|---|
key | string | required | The form key from the dashboard. |
fields | Fields | required | Every field the form can submit. Sent to the server at init and frozen. See field config. |
validateOn | 'submit' | 'blur' | 'submit' | blur validates each field on the server as the visitor leaves it. Validation |
initOn | 'interaction' | 'mount' | 'interaction' | When the server session opens. mount opens it immediately and is scored as bot-like; avoid it. Spam protection |
apiBase | string | https://api.snipform.io/v2 | API base URL. |
onSuccess | (result: SubmitSuccess) => void | Called after a successful submit. | |
onValidationError | (errors: FieldErrors) => void | Called when a submit fails validation. | |
onError | (error: SnipFormError) => void | Called on any init or submit failure, fatal or recoverable. |
Field config
Section titled “Field config”type Fields = Record<string, { type?: FieldType; // default 'text' rules?: RuleMessages; // { ruleName: message | null } initial?: string | string[];}>;| Key | |
|---|---|
type | One of text email tel url number password hidden date textarea select select-multiple radio checkbox. Drives how register() binds the input and how the server reads the value. checkbox and select-multiple produce arrays. |
rules | Rule name to message. null uses the server’s default message. Parameters go in square brackets: 'max_length[120]'. A field with no rules is optional and accepts anything. |
initial | Starting value. Defaults to '', or [] for checkbox and select-multiple. |
The handle
Section titled “The handle”| Property | Type | |
|---|---|---|
status | Status | 'idle' | 'initializing' | 'ready' | 'submitting' | 'success' | 'error' | 'fatal'. See lifecycle. |
values | Record<string, string | string[]> | Current values keyed by field name. |
errors | FieldErrors | { field: [message, ...] }. Every message the server returned, not just the first. |
fatal | string | null | The form cannot run: bad key, unpublished form, domain not allowed, unknown rule name. Show this instead of the form. |
error | SnipFormError | null | A recoverable failure from the last init or submit (network, 403, 5xx). |
success | SubmitSuccess | null | { html, values } after a successful submit. html is the form’s thank-you content with %field% variables already substituted by the server. |
branding | { label, link } | null | Present when the plan requires a “powered by” link. Render with <Branding>. |
isReady | boolean | status === 'ready' |
isSubmitting | boolean | status === 'submitting' |
Actions
Section titled “Actions”| Method | |
|---|---|
register(name, { value? }) | Props for an input, select or textarea bound to name. Pass value for each option of a checkbox group or radio set. Inputs |
setValue(name, value) | Set a value programmatically. Counts as touching the field. |
fieldError(name) | The first message for a field, or undefined. |
submit() | Submit now. Returns Promise<void>; outcomes land on the handle. Opens the session first if none is open. No-op while submitting or fatal. |
handleSubmit(event) | submit() wrapped with preventDefault(). <SnipForm> wires this to onSubmit. |
validate(field?) | Server-validate the current values without submitting. Returns the error bag and applies it: all fields, or only field when given. Resolves to {} when no session is open. |
reset() | Back to idle: initial values, no errors, no success, session dropped. The next interaction opens a new session. |
Props bundles
Section titled “Props bundles”| Property | |
|---|---|
formProps | Spread onto your own <form> when you do not use <SnipForm>: ref, noValidate, onSubmit, and capture-phase onFocusCapture / onClickCapture / onKeyDownCapture / onTouchStartCapture that open the human gate. The ref is also what lets the hook notice the form scrolling into view. |
honeypotProps | null until the session is open, then props for the bot-trap input: name, value: '', tabIndex: -1, autoComplete: 'off', aria-hidden, readOnly, and an off-screen style. Spread onto an <input> or render <Honeypot form={form} />. |
// Equivalent to <SnipForm form={form}>...</SnipForm><form {...form.formProps} className="space-y-4"> ... <Honeypot form={form} /></form>Lifecycle
Section titled “Lifecycle”idle ──(first interaction)──▶ initializing ──▶ ready ──(submit)──▶ submitting ──▶ success │ │ ▼ ├──▶ ready (validation errors) fatal └──▶ error (network, 403, 5xx)| Status | Meaning | Typical render |
|---|---|---|
idle | Mounted, no session yet. Nothing has been sent. | The form, fully interactive. |
initializing | First interaction happened, session opening. | The form. Inputs keep working; values are kept. |
ready | Session open. Also the state after a validation failure. | The form, with errors if any. |
submitting | Request in flight. | Disable the button: disabled={form.isSubmitting}. |
success | Submitted. The session is consumed. | success.html or your own thank-you. |
error | A recoverable failure. error holds the reason. Submitting again is allowed. | The form plus a retry message. |
fatal | The form cannot run. fatal holds the server’s message. | The message instead of the form. |
The session that initializing opens is the one described in How Forms Work: it lives 600 seconds, is pinned to the visitor’s connection and is consumed by a successful submit. When a submit hits an expired session the hook opens a new one and retries once, transparently.
Everything is exported:
import type { SnipFormOptions, SnipFormHandle, Fields, FieldConfig, FieldType, FieldValue, RuleMessages, FieldErrors, FieldProps, FormProps, HoneypotProps, RegisterOptions, Status, SubmitSuccess, ErrorKind, BrandingInfo,} from '@snipform/react';import { SnipFormError } from '@snipform/react';SnipFormError carries message, kind ('fatal' | 'expired' | 'unauthorized' | 'network' | 'server') and the HTTP status when there was one. What each kind means is covered in States.