Solid

作者 vercel-labsfc2a696a50a3無授權條款18K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫昨天更新

SolidJS renderer for json-render. Use when building @json-render/solid catalogs/registries, wiring Renderer providers, implementing bindings/actions, or troubleshooting Solid-specific reactivity patterns.

精選僅含說明Software Development
AI 產生的概覽

指導為 json-render 建置 SolidJS 渲染器:目錄、登錄檔、Provider、綁定、動作與反應式。

功能
此技能說明如何使用 @json-render/solid 套件,將 json-render 規格渲染成具備細緻反應式的 Solid 元件樹。內容涵蓋以 defineCatalog 與 Zod schema 建立目錄、以 defineRegistry 定義元件與登錄檔、接上 JSONUIProvider 等 Provider,以及使用狀態、可見性、驗證與動作相關 hooks。也說明規格結構、動態屬性與綁定、內建動作、串流 UI 以及 Solid 特有的反應式規則。
適用情境
適用於建置 @json-render/solid 目錄或登錄檔、接上 Renderer Provider、實作綁定或動作,或排查 Solid 特有的反應式問題。適合將 json-render 規格整合到 SolidJS 應用程式的開發者。
執行需求
需要 @json-render/solid 與 @json-render/core 套件以及 zod,並需要支援 JSX/TSX 的 SolidJS 專案。僅為說明文件,未附帶指令碼。

@json-render/solid

@json-render/solid renders json-render specs into Solid component trees with fine-grained reactivity.

Quick Start

tsx
import { Renderer, JSONUIProvider } from "@json-render/solid";import type { Spec } from "@json-render/solid";import { registry } from "./registry";
export function App(props: { spec: Spec | null }) {  return (    <JSONUIProvider registry={registry} initialState={{}}>      <Renderer spec={props.spec} registry={registry} />    </JSONUIProvider>  );}

Create a Catalog

typescript
import { defineCatalog } from "@json-render/core";import { schema } from "@json-render/solid/schema";import { z } from "zod";
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() }),      description: "Card container",    },  },  actions: {    submit: { description: "Submit data" },  },});

Define Components

Components receive ComponentRenderProps from the renderer:

ts
interface ComponentRenderProps<P = Record<string, unknown>> {  element: UIElement<string, P>;  children?: JSX.Element;  emit: (event: string) => void;  on: (event: string) => EventHandle;  bindings?: Record<string, string>;  loading?: boolean;}

Example:

tsx
import type { BaseComponentProps } from "@json-render/solid";
export function Button(props: BaseComponentProps<{ label: string }>) {  return (    <button onClick={() => props.emit("press")}>{props.props.label}</button>  );}

Create a Registry

typescript
import { defineRegistry } from "@json-render/solid";import { catalog } from "./catalog";import { Card } from "./Card";import { Button } from "./Button";
const { registry, handlers, executeAction } = defineRegistry(catalog, {  components: {    Card,    Button,  },  actions: {    submit: async (params, setState, state) => {      // custom action logic    },  },});

Spec Structure

json
{  "root": "card1",  "elements": {    "card1": {      "type": "Card",      "props": { "title": "Hello" },      "children": ["btn1"]    },    "btn1": {      "type": "Button",      "props": { "label": "Click me" },      "on": {        "press": { "action": "submit" }      }    }  }}

Providers

  • StateProvider: state model read/write and controlled mode via store
  • VisibilityProvider: evaluates visible conditions
  • ValidationProvider: field validation + validateForm integration
  • ActionProvider: runs built-in and custom actions
  • JSONUIProvider: combined provider wrapper

Hooks

  • useStateStore, useStateValue, useStateBinding
  • useVisibility, useIsVisible
  • useActions, useAction
  • useValidation, useOptionalValidation, useFieldValidation
  • useBoundProp
  • useUIStream, useChatUI

Built-in Actions

Handled automatically by ActionProvider:

  • setState
  • pushState
  • removeState
  • validateForm

Dynamic Props and Bindings

Nested lists can set repeat.statePath to { "$item": "field" } inside an enclosing repeat.

Supported expression forms include:

  • {"$state": "/path"}
  • {"$bindState": "/path"}
  • {"$bindItem": "field"}
  • {"$template": "Hi ${/user/name}"}
  • {"$computed": "fn", "args": {...}}
  • {"$cond": <condition>, "$then": <value>, "$else": <value>}

Use useBoundProp in components for writable bound values:

tsx
import { useBoundProp } from "@json-render/solid";
function Input(props: BaseComponentProps<{ value?: string }>) {  const [value, setValue] = useBoundProp(    props.props.value,    props.bindings?.value,  );  return (    <input      value={String(value() ?? "")}      onInput={(e) => setValue(e.currentTarget.value)}    />  );}

useStateValue, useStateBinding, and the state / errors / isValid fields from useFieldValidation are reactive accessors in Solid. Call them as functions inside JSX, createMemo, or createEffect.

Solid Reactivity Rules

  • Do not destructure component props in function signatures when values need to stay reactive.
  • Keep changing reads inside JSX expressions, createMemo, or createEffect.
  • Context values are exposed through getter-based objects so consumers always observe live signals.

Streaming UI

tsx
import { useUIStream, Renderer } from "@json-render/solid";
const stream = useUIStream({ api: "/api/generate-ui" });await stream.send("Create a support dashboard");
<Renderer  spec={stream.spec}  registry={registry}  loading={stream.isStreaming}/>;

Use useChatUI for chat + UI generation flows.

來源與署名

來源:vercel-labs/json-render位於skills/solid提交fc2a696

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架