A production-focused playground for live editing React code with real-time preview capabilities
—
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.
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.
/**
* Synchronously transforms and executes JSX code to produce a React component
* @param options - Code transformation options
* @param errorCallback - Function called when transformation or execution errors occur
* @returns React ComponentType ready for rendering
*/
function generateElement(
options: {
/** The JSX/TypeScript code to transform and execute */
code: string;
/** Variables available in the code execution context */
scope?: Record<string, unknown>;
/** Whether to enable TypeScript transformations */
enableTypeScript: boolean;
},
errorCallback: (error: Error) => void
): ComponentType;Usage Examples:
import { generateElement } from "react-live";
// Basic JSX transformation
const simpleCode = '<h1>Hello World</h1>';
const SimpleComponent = generateElement(
{
code: simpleCode,
enableTypeScript: false
},
(error) => console.error('Generation failed:', error)
);
// With scope variables
const scopedCode = `
<div>
<Button onClick={handleClick}>
{buttonText}
</Button>
</div>
`;
const ScopedComponent = generateElement(
{
code: scopedCode,
scope: {
Button: MyButtonComponent,
handleClick: () => alert('Clicked!'),
buttonText: 'Click Me'
},
enableTypeScript: true
},
(error) => console.error('Generation failed:', error)
);
// TypeScript with interfaces
const typedCode = `
interface User {
name: string;
age: number;
}
const user: User = { name: 'Alice', age: 30 };
<div>
<h2>{user.name}</h2>
<p>Age: {user.age}</p>
</div>
`;
const TypedComponent = generateElement(
{
code: typedCode,
enableTypeScript: true
},
(error) => console.error('TypeScript error:', error)
);
// Custom error handling
function createComponent(code: string) {
let hasError = false;
let errorMessage = '';
const component = generateElement(
{ code, enableTypeScript: true },
(error) => {
hasError = true;
errorMessage = error.message;
}
);
return { component, hasError, errorMessage };
}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.
/**
* Asynchronously renders code that uses the render() function (no-inline mode)
* @param options - Code transformation options
* @param resultCallback - Function called with the successfully rendered component
* @param errorCallback - Function called when transformation or execution errors occur
*/
function renderElementAsync(
options: {
/** The code containing render() calls */
code: string;
/** Variables available in the code execution context */
scope?: Record<string, unknown>;
/** Whether to enable TypeScript transformations */
enableTypeScript: boolean;
},
resultCallback: (component: ComponentType) => void,
errorCallback: (error: Error) => void
): void;Usage Examples:
import { renderElementAsync } from "react-live";
// Basic no-inline rendering
const noInlineCode = `
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>;
}
render(<Welcome name="World" />);
`;
renderElementAsync(
{
code: noInlineCode,
enableTypeScript: true
},
(component) => {
console.log('Component ready:', component);
// Use component for rendering
},
(error) => {
console.error('Rendering failed:', error);
}
);
// With complex component logic
const complexCode = `
function UserCard({ user }) {
const [expanded, setExpanded] = useState(false);
return (
<div className="user-card">
<h3>{user.name}</h3>
<button onClick={() => setExpanded(!expanded)}>
{expanded ? 'Collapse' : 'Expand'}
</button>
{expanded && (
<div>
<p>Email: {user.email}</p>
<p>Age: {user.age}</p>
</div>
)}
</div>
);
}
const sampleUser = {
name: 'Alice Johnson',
email: 'alice@example.com',
age: 28
};
render(<UserCard user={sampleUser} />);
`;
renderElementAsync(
{
code: complexCode,
scope: {
useState: React.useState
},
enableTypeScript: true
},
(component) => {
// Component with hooks ready to render
setCurrentComponent(component);
},
(error) => {
setErrorMessage(error.message);
}
);
// Multiple component rendering
const multiComponentCode = `
function Header() {
return <h1>My App</h1>;
}
function Footer() {
return <footer>© 2024</footer>;
}
function App() {
return (
<div>
<Header />
<main>
<p>Welcome to my application!</p>
</main>
<Footer />
</div>
);
}
render(<App />);
`;
renderElementAsync(
{
code: multiComponentCode,
enableTypeScript: false
},
(component) => {
// Multi-component app ready
mountComponent(component);
},
(error) => {
displayError(error.message);
}
);
// Error handling patterns
function safeRenderAsync(code: string, scope = {}) {
return new Promise((resolve, reject) => {
renderElementAsync(
{
code,
scope,
enableTypeScript: true
},
(component) => {
resolve(component);
},
(error) => {
reject(new Error(`Render failed: ${error.message}`));
}
);
});
}
// Usage with async/await
async function handleCodeChange(newCode: string) {
try {
const component = await safeRenderAsync(newCode, {
useState: React.useState,
useEffect: React.useEffect
});
setPreviewComponent(component);
} catch (error) {
setError(error.message);
}
}The code transformation process follows these steps:
<h1>Hello</h1> becomes return (<h1>Hello</h1>)render() functionrender(<MyComponent />)// Common error scenarios handled by transformation functions:
// Syntax errors in JSX/TypeScript
SyntaxError: "Unexpected token '<'"
// Runtime errors during component execution
ReferenceError: "CustomComponent is not defined"
// No-inline mode specific errors
SyntaxError: "No-Inline evaluations must call `render`"
SyntaxError: "`render` must be called with valid JSX"
// Transformation errors
Error: "Code failed to transform"// Custom transformation wrapper
function createLiveTransformer(defaultScope: Record<string, unknown>) {
return {
transformInline: (code: string, additionalScope = {}) => {
const scope = { ...defaultScope, ...additionalScope };
return generateElement({ code, scope, enableTypeScript: true }, console.error);
},
transformAsync: (code: string, additionalScope = {}) => {
const scope = { ...defaultScope, ...additionalScope };
return new Promise((resolve, reject) => {
renderElementAsync(
{ code, scope, enableTypeScript: true },
resolve,
reject
);
});
}
};
}
// Usage
const transformer = createLiveTransformer({
React,
useState: React.useState,
useEffect: React.useEffect
});
const InlineComponent = transformer.transformInline('<h1>Inline</h1>');
const AsyncComponent = await transformer.transformAsync(`
function App() { return <div>Async</div>; }
render(<App />);
`);Install with Tessl CLI
npx tessl i tessl/npm-react-live