0
# Code Transformation
1
2
Low-level utilities for transforming and executing JSX/TypeScript code in real-time. These functions power the LiveProvider component but are also available for custom implementations and advanced use cases.
3
4
## Capabilities
5
6
### generateElement
7
8
Synchronously transforms and executes JSX code to produce a React component. This function handles the complete pipeline from raw code to executable React elements, including TypeScript compilation, JSX transformation, and safe evaluation.
9
10
```typescript { .api }
11
/**
12
* Synchronously transforms and executes JSX code to produce a React component
13
* @param options - Code transformation options
14
* @param errorCallback - Function called when transformation or execution errors occur
15
* @returns React ComponentType ready for rendering
16
*/
17
function generateElement(
18
options: {
19
/** The JSX/TypeScript code to transform and execute */
20
code: string;
21
/** Variables available in the code execution context */
22
scope?: Record<string, unknown>;
23
/** Whether to enable TypeScript transformations */
24
enableTypeScript: boolean;
25
},
26
errorCallback: (error: Error) => void
27
): ComponentType;
28
```
29
30
**Usage Examples:**
31
32
```typescript
33
import { generateElement } from "react-live";
34
35
// Basic JSX transformation
36
const simpleCode = '<h1>Hello World</h1>';
37
const SimpleComponent = generateElement(
38
{
39
code: simpleCode,
40
enableTypeScript: false
41
},
42
(error) => console.error('Generation failed:', error)
43
);
44
45
// With scope variables
46
const scopedCode = `
47
<div>
48
<Button onClick={handleClick}>
49
{buttonText}
50
</Button>
51
</div>
52
`;
53
54
const ScopedComponent = generateElement(
55
{
56
code: scopedCode,
57
scope: {
58
Button: MyButtonComponent,
59
handleClick: () => alert('Clicked!'),
60
buttonText: 'Click Me'
61
},
62
enableTypeScript: true
63
},
64
(error) => console.error('Generation failed:', error)
65
);
66
67
// TypeScript with interfaces
68
const typedCode = `
69
interface User {
70
name: string;
71
age: number;
72
}
73
74
const user: User = { name: 'Alice', age: 30 };
75
76
<div>
77
<h2>{user.name}</h2>
78
<p>Age: {user.age}</p>
79
</div>
80
`;
81
82
const TypedComponent = generateElement(
83
{
84
code: typedCode,
85
enableTypeScript: true
86
},
87
(error) => console.error('TypeScript error:', error)
88
);
89
90
// Custom error handling
91
function createComponent(code: string) {
92
let hasError = false;
93
let errorMessage = '';
94
95
const component = generateElement(
96
{ code, enableTypeScript: true },
97
(error) => {
98
hasError = true;
99
errorMessage = error.message;
100
}
101
);
102
103
return { component, hasError, errorMessage };
104
}
105
```
106
107
### renderElementAsync
108
109
Asynchronously renders code that uses the `render()` function pattern (no-inline mode). This is used for more complex scenarios where the code needs to explicitly call a render function rather than returning JSX directly.
110
111
```typescript { .api }
112
/**
113
* Asynchronously renders code that uses the render() function (no-inline mode)
114
* @param options - Code transformation options
115
* @param resultCallback - Function called with the successfully rendered component
116
* @param errorCallback - Function called when transformation or execution errors occur
117
*/
118
function renderElementAsync(
119
options: {
120
/** The code containing render() calls */
121
code: string;
122
/** Variables available in the code execution context */
123
scope?: Record<string, unknown>;
124
/** Whether to enable TypeScript transformations */
125
enableTypeScript: boolean;
126
},
127
resultCallback: (component: ComponentType) => void,
128
errorCallback: (error: Error) => void
129
): void;
130
```
131
132
**Usage Examples:**
133
134
```typescript
135
import { renderElementAsync } from "react-live";
136
137
// Basic no-inline rendering
138
const noInlineCode = `
139
function Welcome({ name }) {
140
return <h1>Hello, {name}!</h1>;
141
}
142
143
render(<Welcome name="World" />);
144
`;
145
146
renderElementAsync(
147
{
148
code: noInlineCode,
149
enableTypeScript: true
150
},
151
(component) => {
152
console.log('Component ready:', component);
153
// Use component for rendering
154
},
155
(error) => {
156
console.error('Rendering failed:', error);
157
}
158
);
159
160
// With complex component logic
161
const complexCode = `
162
function UserCard({ user }) {
163
const [expanded, setExpanded] = useState(false);
164
165
return (
166
<div className="user-card">
167
<h3>{user.name}</h3>
168
<button onClick={() => setExpanded(!expanded)}>
169
{expanded ? 'Collapse' : 'Expand'}
170
</button>
171
{expanded && (
172
<div>
173
<p>Email: {user.email}</p>
174
<p>Age: {user.age}</p>
175
</div>
176
)}
177
</div>
178
);
179
}
180
181
const sampleUser = {
182
name: 'Alice Johnson',
183
email: 'alice@example.com',
184
age: 28
185
};
186
187
render(<UserCard user={sampleUser} />);
188
`;
189
190
renderElementAsync(
191
{
192
code: complexCode,
193
scope: {
194
useState: React.useState
195
},
196
enableTypeScript: true
197
},
198
(component) => {
199
// Component with hooks ready to render
200
setCurrentComponent(component);
201
},
202
(error) => {
203
setErrorMessage(error.message);
204
}
205
);
206
207
// Multiple component rendering
208
const multiComponentCode = `
209
function Header() {
210
return <h1>My App</h1>;
211
}
212
213
function Footer() {
214
return <footer>© 2024</footer>;
215
}
216
217
function App() {
218
return (
219
<div>
220
<Header />
221
<main>
222
<p>Welcome to my application!</p>
223
</main>
224
<Footer />
225
</div>
226
);
227
}
228
229
render(<App />);
230
`;
231
232
renderElementAsync(
233
{
234
code: multiComponentCode,
235
enableTypeScript: false
236
},
237
(component) => {
238
// Multi-component app ready
239
mountComponent(component);
240
},
241
(error) => {
242
displayError(error.message);
243
}
244
);
245
246
// Error handling patterns
247
function safeRenderAsync(code: string, scope = {}) {
248
return new Promise((resolve, reject) => {
249
renderElementAsync(
250
{
251
code,
252
scope,
253
enableTypeScript: true
254
},
255
(component) => {
256
resolve(component);
257
},
258
(error) => {
259
reject(new Error(`Render failed: ${error.message}`));
260
}
261
);
262
});
263
}
264
265
// Usage with async/await
266
async function handleCodeChange(newCode: string) {
267
try {
268
const component = await safeRenderAsync(newCode, {
269
useState: React.useState,
270
useEffect: React.useEffect
271
});
272
setPreviewComponent(component);
273
} catch (error) {
274
setError(error.message);
275
}
276
}
277
```
278
279
## Transformation Pipeline
280
281
The code transformation process follows these steps:
282
283
1. **Input Validation**: Verify code is a valid string
284
2. **TypeScript Compilation**: Transform TypeScript to JavaScript (if enabled)
285
3. **JSX Transformation**: Convert JSX syntax to React.createElement calls
286
4. **Import Resolution**: Handle ES6 import statements
287
5. **Code Wrapping**: Add necessary wrapper code (for inline mode)
288
6. **Safe Evaluation**: Execute code in controlled environment with provided scope
289
7. **Error Boundary**: Wrap result in error boundary for safe rendering
290
291
## Code Execution Modes
292
293
### Inline Mode (generateElement)
294
295
- Code is automatically wrapped in a return statement
296
- Suitable for simple JSX expressions
297
- Direct evaluation and immediate component return
298
- Example: `<h1>Hello</h1>` becomes `return (<h1>Hello</h1>)`
299
300
### No-Inline Mode (renderElementAsync)
301
302
- Code must explicitly call `render()` function
303
- Suitable for complex component definitions
304
- Allows multiple component definitions before rendering
305
- Example: Code must contain `render(<MyComponent />)`
306
307
## Error Types
308
309
```typescript { .api }
310
// Common error scenarios handled by transformation functions:
311
312
// Syntax errors in JSX/TypeScript
313
SyntaxError: "Unexpected token '<'"
314
315
// Runtime errors during component execution
316
ReferenceError: "CustomComponent is not defined"
317
318
// No-inline mode specific errors
319
SyntaxError: "No-Inline evaluations must call `render`"
320
SyntaxError: "`render` must be called with valid JSX"
321
322
// Transformation errors
323
Error: "Code failed to transform"
324
```
325
326
## Advanced Usage
327
328
```typescript
329
// Custom transformation wrapper
330
function createLiveTransformer(defaultScope: Record<string, unknown>) {
331
return {
332
transformInline: (code: string, additionalScope = {}) => {
333
const scope = { ...defaultScope, ...additionalScope };
334
return generateElement({ code, scope, enableTypeScript: true }, console.error);
335
},
336
337
transformAsync: (code: string, additionalScope = {}) => {
338
const scope = { ...defaultScope, ...additionalScope };
339
return new Promise((resolve, reject) => {
340
renderElementAsync(
341
{ code, scope, enableTypeScript: true },
342
resolve,
343
reject
344
);
345
});
346
}
347
};
348
}
349
350
// Usage
351
const transformer = createLiveTransformer({
352
React,
353
useState: React.useState,
354
useEffect: React.useEffect
355
});
356
357
const InlineComponent = transformer.transformInline('<h1>Inline</h1>');
358
const AsyncComponent = await transformer.transformAsync(`
359
function App() { return <div>Async</div>; }
360
render(<App />);
361
`);
362
```