Interactive JSX Previewer for AI Coding Platforms
When working with AI-generated code, especially in React applications, being able to instantly preview JSX output becomes crucial. The JSXPreview
component solves this challenge by rendering JSX strings as React components in real-time, with support for streaming content and automatic tag completion.
The Problem with AI-Generated JSX
AI models often generate JSX code incrementally, which can lead to incomplete tags and broken rendering. Traditional approaches require waiting for the complete output before rendering, creating a disjointed experience for users.
Introducing JSX Preview
Our JSXPreview
component solves these problems with two key features:
- Direct JSX Rendering: Convert JSX strings to live React components
- Tag Completion: Automatically complete open tags during streaming
JSX Input
Preview
How It Works
The component works through a combination of JSX parsing and intelligent tag completion:
function JSXPreview({ jsx, isStreaming = false, ...props }: JSXPreviewProps) {
const processedJsx = React.useMemo(
() => (isStreaming ? completeJsxTag(jsx) : jsx),
[jsx, isStreaming]
)
// Cast JsxParser to any to work around the type incompatibility
const Parser = JsxParser as unknown as React.ComponentType<JsxParserProps>
return <Parser jsx={processedJsx} {...props} />
}
When isStreaming
is enabled, the component automatically balances opening and closing tags, allowing for real-time preview even with incomplete JSX input.
Tag Completion Logic
The core of our component lies in the completeJsxTag
function:
function completeJsxTag(code: string) {
const stack: string[] = []
let result = ""
let currentPosition = 0
while (currentPosition < code.length) {
const match = matchJsxTag(code.slice(currentPosition))
if (!match) break
const { tagName, type, endIndex } = match
if (type === "opening") {
stack.push(tagName)
} else if (type === "closing") {
stack.pop()
}
result += code.slice(currentPosition, currentPosition + endIndex)
currentPosition += endIndex
}
return (
result +
stack
.reverse()
.map((tag) => `</${tag}>`)
.join("")
)
}
This function maintains a stack of open tags and automatically generates closing tags when needed, ensuring valid JSX even during streaming.
Usage Examples
Basic JSX Preview
import { JSXPreview } from "@/components/jsxPreview";
export default function Example() {
return (
<JSXPreview
jsx="<div><h1>Hello World</h1><p>This is a preview</p></div>"
/>
);
}
Streaming JSX Preview
import { JSXPreview } from "@/components/jsxPreview";
import { useState, useEffect } from "react";
export default function StreamingExample() {
const [jsx, setJsx] = useState("");
useEffect(() => {
const fullJsx = "<div><h1>Hello World</h1><p>This is being streamed";
let current = "";
let index = 0;
const interval = setInterval(() => {
if (index < fullJsx.length) {
current += fullJsx[index];
setJsx(current);
index++;
} else {
clearInterval(interval);
}
}, 100);
return () => clearInterval(interval);
}, []);
return <JSXPreview jsx={jsx} isStreaming={true} />;
}
Use Cases
AI Code Generation
The JSXPreview
component is particularly useful when integrated with AI code generation tools:
- Real-time preview of AI-generated components
- Visual feedback during iterative code generation
- Interactive prototyping with AI assistance
Credits
This component was inspired by the work done at Prompt Kit, which offers various tools for working with AI-generated content.