跳到正文
cccskills
免费在 GitHub 公开

react

Turn JSON specifications into React interfaces using a catalog of available components. This skill helps connect component implementations, shared data, form inputs, conditional display, and user actions to render interactive screens, including AI-generated designs.

中文简介正在准备中。当前显示英语简介。

原文查看原文说明

React renderer for json-render that turns JSON specs into React components. Use when working with @json-render/react, building React UIs from JSON, creating component catalogs, or rendering AI-generated specs.

查看安装方法

适用场景

  • Render AI-generated JSON as a React interface
  • Define a catalog of reusable UI components
  • Connect form inputs to shared data
  • Filter lists and show content conditionally

包含的文件(1)

  • SKILL.md11.5 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

@json-render/react

React renderer that converts JSON specs into React component trees.

Quick Start

import { defineRegistry, Renderer } from "@json-render/react";
import { catalog } from "./catalog";

const { registry } = defineRegistry(catalog, {
  components: {
    Card: ({ props, children }) => <div>{props.title}{children}</div>,
  },
});

function App({ spec }) {
  return <Renderer spec={spec} registry={registry} />;
}

Creating a Catalog

import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/react/schema";
import { defineRegistry } from "@json-render/react";
import { z } from "zod";

// Create catalog with props schemas
export const catalog = defineCatalog(schema, {
  components: {
    Button: {
      props: z.object({
        label: z.string(),
        variant: z.enum(["primary", "secondary"]).nullable(),
      }),
      description: "Clickable button",
    },
    Card: {
      props: z.object({ title: z.string() }),
      slots: ["default"],
      description: "Card container with title",
    },
    Layout: {
      props: z.object({}),
      slots: ["default", "header", "footer"],
      description: "Layout with named content regions",
    },
  },
});

// Define component implementations with type-safe props
const { registry } = defineRegistry(catalog, {
  components: {
    Button: ({ props }) => (
      <button className={props.variant}>{props.label}</button>
    ),
    Card: ({ props, children }) => (
      <div className="card">
        <h2>{props.title}</h2>
        {children}
      </div>
    ),
    Layout: ({ children, slots }) => (
      <div>
        <header>{slots?.header}</header>
        <main>{children}</main>
        <footer>{slots?.footer}</footer>
      </div>
    ),
  },
});

Spec Structure (Element Tree)

The React schema uses an element tree format:

{
  "root": {
    "type": "Card",
    "props": { "title": "Hello" },
    "children": [{ "type": "Button", "props": { "label": "Click me" } }]
  }
}

Named Slots

Use children for the "default" slot. Use the element's top-level slots object for other slot names declared by the catalog:

{
  "type": "Layout",
  "props": {},
  "children": ["main"],
  "slots": {
    "header": ["heading"],
    "footer": ["actions"]
  }
}

Registry components receive named content as slots?.header, slots?.footer, and so on. Do not use slots.default.

Visibility Conditions

Use visible on elements to show/hide based on state. New syntax: { "$state": "/path" }, { "$state": "/path", "eq": value }, { "$state": "/path", "not": true }, { "$and": [cond1, cond2] } for AND, { "$or": [cond1, cond2] } for OR. Helpers: visibility.when("/path"), visibility.unless("/path"), visibility.eq("/path", val), visibility.and(cond1, cond2), visibility.or(cond1, cond2).

Providers

ProviderPurpose
StateProviderShare state across components (JSON Pointer paths). Accepts optional store prop for controlled mode.
ActionProviderHandle actions dispatched via the event system
VisibilityProviderEnable conditional rendering based on state
ValidationProviderForm field validation

External Store (Controlled Mode)

Pass a StateStore to StateProvider (or JSONUIProvider / createRenderer) to use external state management (Redux, Zustand, XState, etc.):

import { createStateStore, type StateStore } from "@json-render/react";

const store = createStateStore({ count: 0 });

<StateProvider store={store}>{children}</StateProvider>;

// Mutate from anywhere — React re-renders automatically:
store.set("/count", 1);

When store is provided, initialState and onStateChange are ignored.

Dynamic Prop Expressions

Any prop value can be a data-driven expression resolved by the renderer before components receive props:

  • { "$state": "/state/key" } - reads from state model (one-way read)
  • { "$bindState": "/path" } - two-way binding: reads from state and enables write-back. Use on the natural value prop (value, checked, pressed, etc.) of form components.
  • { "$bindItem": "field" } - two-way binding to a repeat item field. Use inside repeat scopes.
  • Filtered lists: repeat plus an $item visible condition on the same container renders only matching items: { "repeat": { "statePath": "/tasks", "key": "id" }, "visible": { "$item": "status", "eq": "todo" }, "children": ["task-card"] }. AND-composed $state conjuncts gate the container shell; $item/$index conjuncts filter items.
  • Nested lists: inside a repeat, use { "repeat": { "statePath": { "$item": "comments" }, "key": "id" } } to iterate an array on the enclosing item.
  • { "$cond": <condition>, "$then": <value>, "$else": <value> } - conditional value
  • { "$template": "Hello, ${/name}!" } - interpolates state values into strings
  • { "$computed": "fn", "args": { ... } } - calls registered functions with resolved args
{
  "type": "Input",
  "props": {
    "value": { "$bindState": "/form/email" },
    "placeholder": "Email"
  }
}

Components do not use a statePath prop for two-way binding. Use { "$bindState": "/path" } on the natural value prop instead.

Components receive already-resolved props. For two-way bound props, use the useBoundProp hook with the bindings map the renderer provides.

Register $computed functions via the functions prop on JSONUIProvider or createRenderer:

<JSONUIProvider
  functions={{ fullName: (args) => `${args.first} ${args.last}` }}
>

Event System

Components use emit to fire named events, or on() to get an event handle with metadata. The element's on field maps events to action bindings:

// Simple event firing
Button: ({ props, emit }) => (
  <button onClick={() => emit("press")}>{props.label}</button>
),

// Event handle with metadata (e.g. preventDefault)
Link: ({ props, on }) => {
  const click = on("click");
  return (
    <a href={props.href} onClick={(e) => {
      if (click.shouldPreventDefault) e.preventDefault();
      click.emit();
    }}>{props.label}</a>
  );
},
{
  "type": "Button",
  "props": { "label": "Submit" },
  "on": { "press": { "action": "submit" } }
}

The EventHandle returned by on() has: emit(), shouldPreventDefault (boolean), and bound (boolean).

State Watchers

Elements can declare a watch field (top-level, sibling of type/props/children) to trigger actions when state values change:

{
  "type": "Select",
  "props": {
    "value": { "$bindState": "/form/country" },
    "options": ["US", "Canada"]
  },
  "watch": { "/form/country": { "action": "loadCities" } },
  "children": []
}

Built-in Actions

The setState, pushState, removeState, and validateForm actions are built into the React schema and handled automatically by ActionProvider. They are injected into AI prompts without needing to be declared in catalog actions:

{ "action": "setState", "params": { "statePath": "/activeTab", "value": "home" } }
{ "action": "pushState", "params": { "statePath": "/items", "value": { "text": "New" } } }
{ "action": "removeState", "params": { "statePath": "/items", "index": 0 } }
{ "action": "validateForm", "params": { "statePath": "/formResult" } }

validateForm validates all registered fields and writes { valid, errors } to state.

Note: statePath in action params (e.g. setState.statePath) targets the mutation path. Two-way binding in component props uses { "$bindState": "/path" } on the value prop, not statePath.

useBoundProp

For form components that need two-way binding, use useBoundProp with the bindings map the renderer provides when a prop uses { "$bindState": "/path" } or { "$bindItem": "field" }:

import { useBoundProp } from "@json-render/react";

Input: ({ element, bindings }) => {
  const [value, setValue] = useBoundProp<string>(
    element.props.value,
    bindings?.value
  );
  return (
    <input
      value={value ?? ""}
      onChange={(e) => setValue(e.target.value)}
    />
  );
},

useBoundProp(propValue, bindingPath) returns [value, setValue]. The value is the resolved prop; setValue writes back to the bound state path (no-op if not bound).

BaseComponentProps

For building reusable component libraries not tied to a specific catalog (e.g. @json-render/shadcn):

import type { BaseComponentProps } from "@json-render/react";

const Card = ({ props, children }: BaseComponentProps<{ title?: string }>) => (
  <div>{props.title}{children}</div>
);

defineRegistry

defineRegistry conditionally requires the actions field only when the catalog declares actions. Catalogs with actions: {} can omit it.

Key Exports

ExportPurpose
defineRegistryCreate a type-safe component registry from a catalog
RendererRender a spec using a registry
schemaElement tree schema (includes built-in state actions: setState, pushState, removeState, validateForm)
useStateStoreAccess state context
useStateValueGet single value from state
useBoundPropTwo-way binding for $bindState/$bindItem expressions
useActionsAccess actions context
useActionGet a single action dispatch function
useOptionalValidationNon-throwing variant of useValidation (returns null if no provider)
useUIStreamStream specs from an API endpoint
createStateStoreCreate a framework-agnostic in-memory StateStore
StateStoreInterface for plugging in external state management
BaseComponentPropsCatalog-agnostic base type for reusable component libraries
EventHandleEvent handle type (emit, shouldPreventDefault, bound)
ComponentContextTyped component context (catalog-aware)

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

codegen

免费

Helps build custom code exporters from json-render UI specifications. Covers walking the UI tree, collecting components, state references, and actions, and formatting property values for JSX, the markup syntax used in React.

中文简介正在准备中。当前显示英语简介。

  • Build a custom exporter for Next.js or Remix
  • List components and actions used in a UI specification
  • Convert property values into JSX attributes
vercel-labs/json-render1.9万2026年10月14日 更新

core

免费

Define the structure and available components for AI-generated JSON screens or videos. Build generation prompts, process incremental updates, connect values to application state, and validate or repair definitions before passing them to a renderer.

中文简介正在准备中。当前显示英语简介。

  • Define allowed components for AI-generated screens
  • Build prompts for generating or editing JSON definitions
  • Assemble definitions from streamed AI responses
vercel-labs/json-render1.9万2026年10月14日 更新

devtools

免费

Debug json-render interfaces with an inspector panel that shows screen specifications, editable runtime state, action history, and streamed updates. Select a rendered page element to locate its definition and investigate display or interaction problems.

中文简介正在准备中。当前显示英语简介。

  • Investigate missing or incorrectly displayed elements
  • Inspect and edit application state at runtime
  • Review action results and errors
vercel-labs/json-render1.9万2026年10月14日 更新

Set up an inspection panel in React json-render apps to examine UI definitions, edit state, and review action and stream timelines. The skill also covers opening or toggling the panel and recording events from React code.

中文简介正在准备中。当前显示英语简介。

  • Adding an inspection panel to a React app
  • Inspecting UI definitions, state, and action history
  • Opening or toggling the panel from React code
vercel-labs/json-render1.9万2026年10月14日 更新

Add and troubleshoot the json-render inspection panel in SolidJS applications. This skill covers panel setup for examining specifications, editing state, reviewing action and stream timelines, browsing component catalogs, and selecting page elements for inspection.

中文简介正在准备中。当前显示英语简介。

  • Add an inspection panel to a SolidJS app
  • Inspect JSON specifications and edit application state
  • Review action and stream timelines
vercel-labs/json-render1.9万2026年10月14日 更新

Add and troubleshoot a developer panel in Svelte 5 json-render apps. Inspect JSON screen definitions, edit application state, review action and streaming timelines, browse component catalogs, and select elements directly from the page.

中文简介正在准备中。当前显示英语简介。

  • Add a developer panel to a Svelte app
  • Inspect screen definitions and edit application state
  • Review action and streaming timelines
vercel-labs/json-render1.9万2026年10月14日 更新

查看 vercel-labs 的全部技能

报告此技能的问题