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 从公开仓库中收录这些内容。

举报或申请下架