Turn a JSON form definition into a real formbridge runtime.
- Useful for CMS-driven forms, experiments, back-office builders, or remote configuration
- The hook parses the definition, preserves field order, and gives you a normal formbridge instance back
- This helper is most compelling when the form shape changes outside the deployed frontend code
- A very practical pattern is “one dynamic step per route” for cross-page wizards whose step definitions come from a backend
Options
Complete useDynamicFormBridge() options surface:
| Method | Type | Description |
|---|---|---|
| 1st argument | JsonFormDefinition | () => Promise<JsonFormDefinition> | Static definition or async loader |
| 2nd argument | UseFormBridgeOptions | All normal useFormBridge() options |
defaultValues? | Record<string, unknown> | Injected after parsing the dynamic schema |
Supported JSON form definition surface:
| Method | Type | Description |
|---|---|---|
JsonFormDefinition | { id?, title?, submitLabel?, fields } | Root JSON structure consumed by the parser |
JsonFieldType | text | email | password | number | tel | url | textarea | checkbox | switch | select | radio | date | otp | hidden | Accepted field types |
JsonFieldDescriptor | { name, type, label, placeholder?, hint?, defaultValue?, required?, min?, max?, pattern?, patternMsg?, options?, otpLength?, disabled?, order?, showWhen?, validate? } | Per-field descriptor shape |
showWhen | { field, value } | { field, notValue } | Visibility rule |
validate entries | required | min | max | pattern | email | url | Typed rule list |
custom | - | Exists in the JSON rule surface today, but the built-in parser does not execute arbitrary custom JSON validators yet |
Because the returned form is a standard bridge instance, submit/error handlers still live on <Form>.
Cross-page / cross-screen wizard pattern
Use useDynamicFormBridge() for cross-page or cross-screen wizards when the backend already decides the fields for each step and the router or navigator already decides which page is active.
- Put the route param in the dynamic loader so each page fetches only its own step definition
- On native, treat the screen param the same way and fetch one step definition per screen
- Set
formKey: stepIdso the form runtime resets cleanly when the route changes - Include the step id in
persist.keyto avoid draft collisions between pages - Submit the current step to your API, then let the router navigate to the next page
- This pattern is ideal when the server owns the canonical onboarding session or partial payload
Return
Complete useDynamicFormBridge() return surface:
| Method | Type | Description |
|---|---|---|
form | UseFormBridgeReturn | null | Standard useFormBridge() return, or null while unavailable |
fieldOrder | string[] | Parser-declared render order |
meta | { id?, title?, submitLabel? } | Metadata extracted from the JSON definition |
isVisible | (name) => boolean | Evaluates dynamic showWhen rules against live values |
isLoading | boolean | true while the async loader resolves |
loadError | string | null | Error message if the loader rejected |
Platform note
Dynamic forms are easiest to adopt in web dashboards first. If you target native too, validate the exact field set and renderer combination you plan to ship, because dynamic helpers tend to surface edge cases later than static schemas.
useDynamicFormBridge()is excellent for one dynamic step per route- If you also want a client-owned wizard state machine with
progress,completedSteps,allValues,goToStep(), and route-driven restoration, preferuseFormBridgeWizard({ stepId, onStepChange })once the step schemas are known in the client