$npx -y skills add vercel-labs/json-render --skill react-nativeReact Native renderer for json-render that turns JSON specs into native mobile UIs. Use when working with @json-render/react-native, building React Native UIs from JSON, creating mobile component catalogs, or rendering AI-generated specs on mobile.
| 1 | # @json-render/react-native |
| 2 | |
| 3 | React Native renderer that converts JSON specs into native mobile component trees with standard components, data binding, visibility, actions, and dynamic props. |
| 4 | |
| 5 | ## Quick Start |
| 6 | |
| 7 | ```typescript |
| 8 | import { defineCatalog } from "@json-render/core"; |
| 9 | import { schema } from "@json-render/react-native/schema"; |
| 10 | import { |
| 11 | standardComponentDefinitions, |
| 12 | standardActionDefinitions, |
| 13 | } from "@json-render/react-native/catalog"; |
| 14 | import { defineRegistry, Renderer, type Components } from "@json-render/react-native"; |
| 15 | import { z } from "zod"; |
| 16 | |
| 17 | // Create catalog with standard + custom components |
| 18 | const catalog = defineCatalog(schema, { |
| 19 | components: { |
| 20 | ...standardComponentDefinitions, |
| 21 | Icon: { |
| 22 | props: z.object({ name: z.string(), size: z.number().nullable(), color: z.string().nullable() }), |
| 23 | slots: [], |
| 24 | description: "Icon display", |
| 25 | }, |
| 26 | }, |
| 27 | actions: standardActionDefinitions, |
| 28 | }); |
| 29 | |
| 30 | // Register only custom components (standard ones are built-in) |
| 31 | const { registry } = defineRegistry(catalog, { |
| 32 | components: { |
| 33 | Icon: ({ props }) => <Ionicons name={props.name} size={props.size ?? 24} />, |
| 34 | } as Components<typeof catalog>, |
| 35 | }); |
| 36 | |
| 37 | // Render |
| 38 | function App({ spec }) { |
| 39 | return ( |
| 40 | <StateProvider initialState={{}}> |
| 41 | <VisibilityProvider> |
| 42 | <ActionProvider handlers={{}}> |
| 43 | <Renderer spec={spec} registry={registry} /> |
| 44 | </ActionProvider> |
| 45 | </VisibilityProvider> |
| 46 | </StateProvider> |
| 47 | ); |
| 48 | } |
| 49 | ``` |
| 50 | |
| 51 | ## Standard Components |
| 52 | |
| 53 | ### Layout |
| 54 | - `Container` - wrapper with padding, background, border radius |
| 55 | - `Row` - horizontal flex layout with gap, alignment |
| 56 | - `Column` - vertical flex layout with gap, alignment |
| 57 | - `ScrollContainer` - scrollable area (vertical or horizontal) |
| 58 | - `SafeArea` - safe area insets for notch/home indicator |
| 59 | - `Pressable` - touchable wrapper that triggers actions on press |
| 60 | - `Spacer` - fixed or flexible spacing |
| 61 | - `Divider` - thin line separator |
| 62 | |
| 63 | ### Content |
| 64 | - `Heading` - heading text (levels 1-6) |
| 65 | - `Paragraph` - body text |
| 66 | - `Label` - small label text |
| 67 | - `Image` - image display with sizing modes |
| 68 | - `Avatar` - circular avatar image |
| 69 | - `Badge` - small status badge |
| 70 | - `Chip` - tag/chip for categories |
| 71 | |
| 72 | ### Input |
| 73 | - `Button` - pressable button with variants |
| 74 | - `TextInput` - text input field |
| 75 | - `Switch` - toggle switch |
| 76 | - `Checkbox` - checkbox with label |
| 77 | - `Slider` - range slider |
| 78 | - `SearchBar` - search input |
| 79 | |
| 80 | ### Feedback |
| 81 | - `Spinner` - loading indicator |
| 82 | - `ProgressBar` - progress indicator |
| 83 | |
| 84 | ### Composite |
| 85 | - `Card` - card container with optional header |
| 86 | - `ListItem` - list row with title, subtitle, accessory |
| 87 | - `Modal` - bottom sheet modal |
| 88 | |
| 89 | ## Visibility Conditions |
| 90 | |
| 91 | Use `visible` on elements. Syntax: `{ "$state": "/path" }`, `{ "$state": "/path", "eq": value }`, `{ "$state": "/path", "not": true }`, `[ cond1, cond2 ]` for AND. |
| 92 | |
| 93 | ## Pressable + setState Pattern |
| 94 | |
| 95 | Use `Pressable` with the built-in `setState` action for interactive UIs like tab bars: |
| 96 | |
| 97 | ```json |
| 98 | { |
| 99 | "type": "Pressable", |
| 100 | "props": { |
| 101 | "action": "setState", |
| 102 | "actionParams": { "statePath": "/activeTab", "value": "home" } |
| 103 | }, |
| 104 | "children": ["home-icon", "home-label"] |
| 105 | } |
| 106 | ``` |
| 107 | |
| 108 | ## Dynamic Prop Expressions |
| 109 | |
| 110 | Any prop value can be a data-driven expression resolved at render time: |
| 111 | |
| 112 | - **`{ "$state": "/state/key" }`** - reads from state model (one-way read) |
| 113 | - **`{ "$bindState": "/path" }`** - two-way binding: use on the natural value prop (value, checked, pressed, etc.) of form components. |
| 114 | - **`{ "$bindItem": "field" }`** - two-way binding to a repeat item field. Use inside repeat scopes. |
| 115 | - **`{ "$cond": <condition>, "$then": <value>, "$else": <value> }`** - conditional value |
| 116 | |
| 117 | ```json |
| 118 | { |
| 119 | "type": "TextInput", |
| 120 | "props": { |
| 121 | "value": { "$bindState": "/form/email" }, |
| 122 | "placeholder": "Email" |
| 123 | } |
| 124 | } |
| 125 | ``` |
| 126 | |
| 127 | Components do not use a `statePath` prop for two-way binding. Use `{ "$bindState": "/path" }` on the natural value prop instead. |
| 128 | |
| 129 | ## Built-in Actions |
| 130 | |
| 131 | The `setState` action is handled automatically by `ActionProvider` and updates the state model directly, which re-evaluates visibility conditions and dynamic prop expressions: |
| 132 | |
| 133 | ```json |
| 134 | { "action": "setState", "actionParams": { "statePath": "/activeTab", "value": "home" } } |
| 135 | ``` |
| 136 | |
| 137 | ## Providers |
| 138 | |
| 139 | | Provider | Purpose | |
| 140 | |----------|---------| |
| 141 | | `StateProvider` | Share state across components (JSON Pointer paths). Accepts optional `store` prop for controlled mode. | |
| 142 | | `ActionProvider` | Handle actions dispatched from components | |
| 143 | | `VisibilityProvider` | Enable conditional rendering based on state | |
| 144 | | `ValidationProvider` | Form field validation | |
| 145 | |
| 146 | ### External Store (Controlled Mode) |
| 147 | |
| 148 | Pass a `StateStore` to `StateProvider` (or `JSONUIProvider` / `createRenderer`) to use external state managemen |