react-formbridge
Browse documentation
Unified Logic Engine

useFormBridge()

The primary interface for React FormBridge. A single, type-safe hook that orchestrates cross-platform form state, validation, and lifecycle events.

The "One Hook" Model

Eliminate environment parity issues. Define your logic once using useFormBridge and deploy to web, native, or desktop shells without forking your state machine.

Quick Start

v2.0.0
import { field, useFormBridge } from '@runilib/react-formbridge'

const schema = {
  fullName: field.text('Full name').required(),
  email: field.email('Email').required().trim().lowercase(),
}

export function ProfileForm() {
  const form = useFormBridge(schema, {
    validateOn: 'onBlur',
    revalidateOn: 'onChange',
    onSubmit: (values) => api.save(values),
  })
  const fullName = form.fieldController('fullName')
  const email = form.fieldController('email')

  return (
    <form onSubmit={form.handleSubmit}>
      <input
        value={fullName.value}
        onChange={(event) => fullName.onChange(event.target.value)}
        onBlur={fullName.onBlur}
      />
      <input
        type="email"
        value={email.value}
        onChange={(event) => email.onChange(event.target.value)}
        onBlur={email.onBlur}
      />
      <button disabled={form.state.isSubmitting}>Save changes</button>
    </form>
  )
}

const api = new Proxy({}, {
  get: (_target, methodName) => async (values) => {
    console.log('[doc-playground]', String(methodName), values)
    return { methodName, values }
  },
})

export default ProfileForm

API Options

PropertyTypeDescription
validateOn'onChange' | 'onBlur' | 'onSubmit' | 'onTouched'Initial validation timing for builder rules. Defaults to `onBlur`.
revalidateOn'onChange' | 'onBlur' | 'onSubmit' | 'onTouched'Follow-up validation trigger after a field has already been interacted with.
validatorBridgeSchemaValidatorBridgeOptional schema adapter for Zod, Yup, Joi, or Valibot validation.
persist{ key: string; storage?: "local" | "session" | "async" | StorageAdapter; ttl?: number; exclude?: string[]; debounce?: number; onRestore?: (values: Record<string, unknown>) => void; onSaveError?: (error: unknown) => void; version?: string; }Draft save and restore behavior with storage, TTL, debounce, and exclusions.
formKeystringRecreate the runtime when the surrounding business context changes.
initialValuesPartial<SchemaValues<typeof schema>>Seed the runtime from existing values before the user edits the form.
schemaKeystring | numberRebuild the compiled schema runtime when its definition changes.
onSubmit(values) => void | Promise<void>Submit callback called after successful validation.
onError(errors) => voidCallback called when validation blocks submission.
onSubmitError(error) => stringMaps a thrown submission error to state.submitError.

Return Value

useFormBridge() returns the runtime surface needed to render forms, inspect live state, and drop into custom UI where needed.

context wrapper

FormProvider

Advanced context wrapper that exposes the form runtime to consumers rendered outside `<Form>`.

form wrapper

Form

Minimal wrapper connected to the submit lifecycle.

standalone error

FieldError

Standalone error renderer for a single field name, useful in custom layouts.

standalone label

FieldLabel

Standalone label renderer for a single field name, useful in custom layouts.

custom renderer bridge

fieldController()

Field-scoped runtime for fully custom UI while keeping the schema contract intact.

reactive state

state

Reactive values, errors, dirty flags, touched state, and submit status.

conditional runtime

visibility

Per-field visibility, required, and disabled flags computed from conditional rules.

draft lifecycle

persistanceHelpers.isLoadingDraft

`true` while a persisted draft is being restored into the runtime.

draft lifecycle

persistanceHelpers.hasDraft

`true` once a previously saved draft was found and hydrated.

draft helper

persistanceHelpers.clearDraft()

Delete the saved draft from the configured storage backend.

draft helper

persistanceHelpers.saveDraftNow()

Persist the current values immediately without waiting for the debounce window.

imperative action

setValue()

Set one field value programmatically from outside the form.

imperative action

getValue()

Read one field value on demand without subscribing to updates.

imperative action

getValues()

Read the full value object on demand without subscribing to updates.

imperative action

validate()

Validate a single field, a list of fields, or the entire form on demand.

imperative action

resetFields()

Reset the form back to schema defaults or to a provided partial value object.

imperative action

setError()

Push a manual field error from imperative code or async handlers.

imperative action

clearErrors()

Clear errors for one field, a list of fields, or the entire form.

reactive helper

watch()

Reactive single-field read that re-renders on every value change.

reactive helper

watchAll()

Reactive full-values read that re-renders on every value change.

imperative action

submit()

Imperatively trigger submission through the validation and submit pipeline.

Type-Safe Errors

Runtime Type Error
// Property '"doesNotExist"' is not assignable to the schema keys
const { setValue } = useFormBridge(schema)

setValue('fullName', 'Ava Stone')
setValue('doesNotExist', 'x')