Render schema-driven values as readonly rows or as a diff against original values.
- Useful for review steps before submission, audit views, change approval screens, or before/after comparisons
- It reuses the schema labels and option metadata, so your review UI stays aligned with your editing UI
Options
- First argument: the schema
Complete useFormBridgeReadonly() options surface:
| Method | Type | Description |
|---|---|---|
mode | 'readonly' | 'diff' | 'readonly' renders plain read-only rows. 'diff' highlights fields whose values[name] differs from originalValues[name] and exposes the before/after pair |
values | SchemaValues<S> | Current values to render - shape comes directly from your schema, so every key is typed |
originalValues? | Partial<SchemaValues<S>> | Baseline values used in diff mode to compute changed / changedFields. Ignored in readonly mode. Fields absent from this map are never flagged as changed |
formatters? | Partial<Record<keyof S, (value) => string>> | Per-field display formatter. Overrides the built-in formatting (dates → toLocaleDateString(), booleans → ✓ Yes / ✗ No, passwords → ••••••••, select/radio → matching option label, empty → -) |
Return
Each fields[name] entry (FieldReadonlyState) contains:
| Method | Type | Description |
|---|---|---|
name | string | The schema key |
label | string | Same label as in the editing form (descriptor._label ?? "") |
value | unknown | Raw value from options.values |
display | string | Formatted, ready-to-render string (custom formatter wins over the built-in one) |
changed | boolean | true only in diff mode when the field has an entry in originalValues and it differs from value (via Object.is) |
original? | unknown | Raw originalValues[name] - present only when changed is true |
originalDisplay? | string | Formatted version of original - useful for rendering a "before" column. Present only when changed is true |
Each generated ReadonlyFields.name(props?) component accepts:
| Method | Type | Description |
|---|---|---|
label? | string | Per-render label override. Falls back to the schema label |
format? | (value) => string | One-off formatter for this render only. Takes precedence over options.formatters[name] and the built-in formatting |
style? | object | Cross-platform inline style forwarded to the readonly renderer's root element |
className? | string | Forwarded className for the web readonly renderer (ignored on native) |
showDiff? | boolean | Force the before/after UI on or off for this render. Defaults to options.mode === 'diff' |
Complete useFormBridgeReadonly() return surface:
| Method | Type | Description |
|---|---|---|
fields | Record<keyof S, FieldReadonlyState> | Computed readonly state for every visible (non-_hidden) field - see the field state table above |
fieldNames | Array<keyof S> | Visible field names in schema iteration order - use this to render rows deterministically instead of Object.keys(fields) |
changedFields | Array<keyof S> | Subset of fieldNames whose changed flag is true. Always empty in readonly mode |
hasChanges | boolean | Shorthand for changedFields.length > 0. Handy for "Nothing changed" empty states |
ReadonlyFields | { [K in keyof S]: (props?) => ReactElement | null } | One ready-to-render component per schema key, reading from fields[name] |
Platform note
Readonly review flows are currently most battle-tested on web. If you plan to rely on this API in native screens too, validate the exact renderer behavior you need before rolling it out broadly.