ObjectUIObjectUI
Core

SchemaRenderer

Core component for rendering JSON schemas into React components

The SchemaRenderer is the heart of ObjectUI. It takes a JSON schema and dynamically renders the appropriate React components based on the schema's type field.

How It Works

The SchemaRenderer uses the Component Registry to look up the appropriate component for each schema type and renders it with the provided props.

import { SchemaRenderer } from '@object-ui/react';

<SchemaRenderer schema={{
  type: 'card',
  title: 'Hello World',
  children: [
    { type: 'text', content: 'This is rendered from JSON!' }
  ]
}} />

Basic Example

Schemarenderer In Action

Dynamic Card
This entire UI is defined in JSON and rendered by SchemaRenderer

Nested Schemas

The SchemaRenderer automatically handles nested schemas:

Nested Schema Example

Parent Component
Nested
Components
Sibling Component
All rendered from a single schema tree

Schema Structure

// abridged: `BaseSchema` in @object-ui/types carries the full member list
interface BaseSchema {
  type: string;                  // Component type (e.g., 'card', 'button', 'text')
  id?: string;                   // Unique identifier
  className?: string;            // Tailwind CSS classes
  children?: BaseSchema | BaseSchema[]; // Child components
}

Every node type extends BaseSchema with its own keys, and none of them carries an index signature (objectui#8347): in a typed literal, a key the node's type does not declare, a misspelling included, is a compile error. A child in a slot is checked against its own type's declaration.

Error Handling

When an unknown component type is encountered, SchemaRenderer displays a helpful error message:

Unknown Component Type

Component Registry

The SchemaRenderer uses the Component Registry to resolve component types:

import { ComponentRegistry } from '@object-ui/core';
import { SchemaRenderer } from '@object-ui/react';
import type { BaseSchema } from '@object-ui/types';

function MyWidgetComponent() {
  return <div>My widget</div>;
}

// Register a custom component
ComponentRegistry.register('my-widget', MyWidgetComponent);

// Declare its node type. A node slot and the `schema` prop take the node types
// `@object-ui/types` declares, plus each type an application adds to
// `CustomNodeRegistry`, so the node below is checked against `MyWidgetSchema`.
interface MyWidgetSchema extends BaseSchema {
  type: 'my-widget';
  customProp?: string;
}

declare module '@object-ui/types' {
  interface CustomNodeRegistry {
    'my-widget': MyWidgetSchema;
  }
}

// Now you can use it in schemas
<SchemaRenderer schema={{
  type: 'my-widget',
  customProp: 'value'
}} />

Usage in Applications

Simple Rendering

import { SchemaRenderer } from '@object-ui/react';
import type { PageNodeSchema } from '@object-ui/types';

function App() {
  const schema: PageNodeSchema = {
    type: 'page',
    pageType: 'app',
    title: 'Dashboard',
    children: [
      { type: 'text', content: 'Welcome to your dashboard' }
    ]
  };

  return <SchemaRenderer schema={schema} />;
}

Dynamic Schemas

import { SchemaRenderer } from '@object-ui/react';
import { useState, useEffect } from 'react';

function DynamicPage() {
  const [schema, setSchema] = useState(null);

  useEffect(() => {
    // Fetch schema from API
    fetch('/api/page-schema')
      .then(res => res.json())
      .then(setSchema);
  }, []);

  if (!schema) return <div>Loading...</div>;

  return <SchemaRenderer schema={schema} />;
}

With Props

You can pass additional props to the rendered component:

<SchemaRenderer 
  schema={{ type: 'button', label: 'Click Me' }}
  onClick={() => console.log('Clicked!')}
  className="extra-classes"
/>

Data Attributes

SchemaRenderer automatically adds data attributes for debugging:

  • data-obj-id: The schema's id field
  • data-obj-type: The schema's type field

These can be used for debugging, testing, or styling:

[data-obj-type="card"] {
  /* Target all card components */
}

Advanced Features

String Rendering

If a schema is just a string, it's rendered as text:

<SchemaRenderer schema="Hello World" />
// Renders: Hello World

Null/Undefined Handling

Null or undefined schemas render nothing:

<SchemaRenderer schema={null} />
// Renders: null

On this page