0
# JSX Support
1
2
Snabbdom provides comprehensive JSX support with factory functions and TypeScript definitions for React-style development patterns.
3
4
## Capabilities
5
6
### JSX Factory Function
7
8
Creates virtual nodes from JSX syntax, supporting both HTML elements and function components.
9
10
```typescript { .api }
11
/**
12
* JSX factory function for creating virtual nodes
13
* @param tag - HTML tag name or function component
14
* @param data - Virtual node data (props, attrs, etc.)
15
* @param children - Child elements
16
* @returns Virtual node
17
*/
18
function jsx(
19
tag: string | FunctionComponent,
20
data: VNodeData | null,
21
...children: JsxVNodeChildren[]
22
): VNode;
23
24
type FunctionComponent = (
25
props: { [prop: string]: any } | null,
26
children?: VNode[]
27
) => VNode;
28
```
29
30
### Fragment Component
31
32
Creates document fragments for grouping elements without wrapper elements (experimental).
33
34
```typescript { .api }
35
/**
36
* JSX Fragment component for grouping elements
37
* @param data - Optional data object with key
38
* @param children - Child elements to group
39
* @returns Virtual node representing a fragment
40
*/
41
function Fragment(
42
data: { key?: Key } | null,
43
...children: JsxVNodeChildren[]
44
): VNode;
45
```
46
47
## TypeScript Configuration
48
49
Add the following to your `tsconfig.json`:
50
51
```json
52
{
53
"compilerOptions": {
54
"jsx": "react",
55
"jsxFactory": "jsx",
56
"jsxFragmentFactory": "Fragment"
57
}
58
}
59
```
60
61
**Usage Example:**
62
63
```typescript
64
import { Fragment, jsx, VNode, init, classModule, styleModule } from "snabbdom";
65
66
const patch = init([classModule, styleModule]);
67
68
// Simple JSX elements
69
const greeting: VNode = <h1>Hello, World!</h1>;
70
71
// Elements with props and children
72
const button: VNode = (
73
<button
74
class={{ primary: true, large: false }}
75
on={{ click: () => console.log("clicked") }}
76
>
77
Click me
78
</button>
79
);
80
81
// Complex JSX structure
82
const app: VNode = (
83
<div class="app">
84
<header>
85
<h1>My Application</h1>
86
</header>
87
<main>
88
<p>Welcome to Snabbdom with JSX!</p>
89
{button}
90
</main>
91
</div>
92
);
93
94
// JSX Fragments (experimental)
95
const fragmentExample: VNode = (
96
<>
97
<p>First paragraph</p>
98
<p>Second paragraph</p>
99
</>
100
);
101
```
102
103
## Babel Configuration
104
105
For JavaScript projects using Babel, add the following to your Babel configuration:
106
107
```json
108
{
109
"plugins": [
110
[
111
"@babel/plugin-transform-react-jsx",
112
{
113
"pragma": "jsx",
114
"pragmaFrag": "Fragment"
115
}
116
]
117
]
118
}
119
```
120
121
**Usage Example:**
122
123
```javascript
124
import { Fragment, jsx } from "snabbdom";
125
126
const component = (
127
<div>
128
<span>I was created with JSX</span>
129
</div>
130
);
131
132
const fragmentComponent = (
133
<>
134
<span>JSX fragments</span>
135
are experimentally supported
136
</>
137
);
138
```
139
140
## Function Components
141
142
Create reusable function components that receive props and return virtual nodes.
143
144
```typescript { .api }
145
type FunctionComponent = (
146
props: { [prop: string]: any } | null,
147
children?: VNode[]
148
) => VNode;
149
```
150
151
**Usage Examples:**
152
153
```typescript
154
import { jsx, VNode, h } from "snabbdom";
155
156
// Simple function component
157
function Greeting(props: { name: string } | null): VNode {
158
return <h1>Hello, {props?.name || "World"}!</h1>;
159
}
160
161
// Function component with children
162
function Card(
163
props: { title: string; className?: string } | null,
164
children?: VNode[]
165
): VNode {
166
return (
167
<div class={props?.className || "card"}>
168
<h2>{props?.title}</h2>
169
<div class="card-body">
170
{children}
171
</div>
172
</div>
173
);
174
}
175
176
// Using function components
177
const app: VNode = (
178
<div>
179
<Greeting name="Snabbdom" />
180
<Card title="Welcome" className="welcome-card">
181
<p>This is card content</p>
182
<button>Action</button>
183
</Card>
184
</div>
185
);
186
```
187
188
## Conditional Rendering
189
190
JSX supports conditional rendering with boolean expressions.
191
192
```typescript
193
import { jsx, VNode } from "snabbdom";
194
195
function ConditionalExample(props: { showMessage: boolean } | null): VNode {
196
return (
197
<div>
198
<h1>Conditional Rendering</h1>
199
{props?.showMessage && <p>This message is conditionally shown</p>}
200
{props?.showMessage ? <p>Condition is true</p> : <p>Condition is false</p>}
201
</div>
202
);
203
}
204
```
205
206
## Working with Lists
207
208
Map over arrays to create lists of elements.
209
210
```typescript
211
import { jsx, VNode } from "snabbdom";
212
213
interface User {
214
id: number;
215
name: string;
216
email: string;
217
}
218
219
function UserList(props: { users: User[] } | null): VNode {
220
const users = props?.users || [];
221
222
return (
223
<ul class="user-list">
224
{users.map(user => (
225
<li key={user.id} class="user-item">
226
<strong>{user.name}</strong> - {user.email}
227
</li>
228
))}
229
</ul>
230
);
231
}
232
233
// Usage
234
const users: User[] = [
235
{ id: 1, name: "Alice", email: "alice@example.com" },
236
{ id: 2, name: "Bob", email: "bob@example.com" }
237
];
238
239
const userListVNode = <UserList users={users} />;
240
```
241
242
## Types
243
244
```typescript { .api }
245
type JsxVNodeChild = VNode | string | number | boolean | undefined | null;
246
type JsxVNodeChildren = ArrayOrElement<JsxVNodeChild>;
247
248
type ArrayOrElement<T> = T | T[];
249
250
namespace jsx {
251
type Element = VNode;
252
253
type VNodeProps<T> = ElementProperties<T> & Props;
254
255
type HtmlElements = {
256
[Property in keyof HTMLElementTagNameMap]: VNodeData<
257
VNodeProps<HTMLElementTagNameMap[Property]>
258
>;
259
};
260
261
interface IntrinsicElements extends HtmlElements {
262
[elemName: string]: VNodeData;
263
}
264
}
265
```