import { useState, useEffect, useMemo, useRef } from "react"; import { Renderer, StateProvider, ActionProvider, VisibilityProvider } from "@json-render/react"; import type { Spec } from "@json-render/core"; import { registry, handlers } from "./registry"; const SPECS = ["simple", "full"] as const; type SetState = (fn: (prev: Record) => Record) => void; function SpecRenderer({ spec }: { spec: Spec }) { const [state, setState] = useState>(spec.state ?? {}); const stateRef = useRef(state); const setStateRef = useRef(setState); stateRef.current = state; setStateRef.current = setState; const actionHandlers = useMemo( () => handlers(() => setStateRef.current, () => stateRef.current), [], ); return ( ); } export function App() { const [activeSpec, setActiveSpec] = useState(null); const [spec, setSpec] = useState(null); const [specJson, setSpecJson] = useState(""); const [jsxSource, setJsxSource] = useState(""); const [loading, setLoading] = useState(false); useEffect(() => { if (!activeSpec) return; setLoading(true); Promise.all([ fetch(`/api/spec/${activeSpec}`).then((r) => r.json()), fetch(`/api/source/${activeSpec}`).then((r) => r.text()), ]) .then(([data, source]) => { setSpec(data); setSpecJson(JSON.stringify(data, null, 2)); setJsxSource(source); }) .finally(() => setLoading(false)); }, [activeSpec]); if (!activeSpec) { return (

jrx examples

JSX → json-render Spec. Pick a spec to see the live UI and JSON output.

{SPECS.map((name) => ( ))}
); } return (

{activeSpec} spec

{loading ? (

Loading...

) : ( spec && (
{/* JSX Source */}

JSX Source

                {jsxSource}
              
{/* Live UI + JSON side by side */}

Live UI

JSON Output

                  {specJson}
                
) )}
); }