Modern applications often need forms that are dynamic, configurable, and reusable.
Instead of hardcoding forms in JSX, many teams adopt schema-driven forms, where the structure of a form is defined using data.
Several libraries implement this idea, including:
- React JSONSchema Form
- JSON Forms
- Uniforms
- Form.io
These tools allow developers to define forms declaratively and generate the UI automatically.
However, they differ significantly in how they separate data, UI, and business logic.
This article compares these approaches and explains why registry-based logic can make schema-driven forms more scalable.
Why Schema-Driven Forms Exist
Traditional React forms often combine multiple responsibilities inside the same component:
- data structure
- UI rendering
- validation logic
- submission workflows
For example:
function UserForm() {
const handleSubmit = (data) => {
validatePassword(data);
api.saveUser(data);
};
return (
<form>
<input name="username" />
<input name="password" />
</form>
);
}
This approach works well for small forms, but it becomes difficult to scale when:
- many forms exist across a platform
- validation rules must be reused
- forms are generated dynamically
- domain-specific field types are needed
Schema-driven forms attempt to solve this by defining forms using structured data.
Three Layers of a Form System
A useful way to analyze form libraries is to look at three concerns:
Data
Defines the structure of the form:
- fields
- data types
- constraints
Usually represented as schemas or JSON definitions.
UI
Responsible for rendering inputs:
- components
- widgets
- layouts
- design system integration
Logic
Handles behavior such as:
- validation
- conditional rules
- submission workflows
- API integration
The key architectural question becomes:
Where does business logic live?
Comparison Overview
| Library | Data | UI | Logic | Decoupling |
|---|---|---|---|---|
| RJSF | JSON Schema | Widgets | Component logic | Medium |
| JSON Forms | JSON Schema | UI Schema | Rules engine | Medium-High |
| Uniforms | Schema adapters | Themes | Component logic | Medium |
| Form.io | JSON definitions | Renderer | Embedded logic | Medium-High |
| Formitiva | Schema definition | Component registry | Registered logic | High |
RJSF
React JSONSchema Form is one of the most popular schema-driven form libraries for React.
It renders forms directly from JSON Schema.
Example:
{
"type": "object",
"properties": {
"username": { "type": "string" },
"age": { "type": "number" }
}
}
The form engine maps schema types to UI components.
Strengths
- strong JSON Schema support
- automatic form generation
- customizable widgets
Limitations
Submission logic typically remains inside the React component:
<Form
schema={schema}
onSubmit={({ formData }) => api.save(formData)}
/>
This means business logic is still tied to UI components.
JSON Forms
JSON Forms introduces a clearer separation between data and UI.
It uses:
- Data Schema (JSON Schema)
- UI Schema (layout definition)
Example UI schema:
{
"type": "VerticalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/username" }
]
}
Strengths
- explicit separation of structure and layout
- rule-based UI behavior
- framework-agnostic architecture
Limitations
Submission workflows and business logic are usually implemented outside the schema.
Uniforms
Uniforms focuses on schema adapters.
It supports multiple schema systems:
- JSON Schema
- GraphQL
- SimpleSchema
Example usage:
<AutoForm schema={schema} onSubmit={saveUser} />
Strengths
- flexible schema support
- good integration with UI frameworks
- minimal boilerplate
Limitations
Validation and workflows are still mostly handled in React logic.
Form.io
Form.io is closer to a complete form platform.
Forms are defined entirely in JSON:
{
"components": [
{
"type": "textfield",
"key": "username"
}
]
}
Strengths
- visual form builder
- dynamic forms
- built-in conditional logic
Limitations
Logic is usually embedded inside the form definition itself, which can reduce reuse across forms.
Architecture Comparison
Different libraries organize form responsibilities differently.
RJSF
Schema → Renderer → Component Logic
JSON Forms
Schema + UI Schema → Renderer → Rules
Uniforms
Schema Adapter → UI Theme → Component Logic
Form.io
Form Definition → Renderer → Embedded Logic
Most approaches successfully separate data and UI, but logic often remains tied to forms or components.
A Registry-Driven Approach
Formitiva takes a different approach.
Instead of embedding logic in schemas or components, it introduces a registry system.
Schemas reference behaviors declaratively:
const definition = {
name: "user_information",
validationHandlerName: "user:passwordMatch",
submitHandlerName: "user:userSubmission",
properties: [
{
name: "username",
type: "text"
}
]
};
The actual implementations are registered separately:
registerFormValidationHandler(
"user:passwordMatch",
passwordMatchValidator
);
registerSubmissionHandler(
"user:userSubmission",
submitUserData
);
Formitiva Architecture
+----------------------+
| Form Schema |
| (Data Layer) |
+----------------------+
|
v
+----------------------+
| Registry |
| (UI + Logic Mapping) |
+----------------------+
|
v
+----------------------+
| Renderer |
| (React UI) |
+----------------------+
This architecture separates:
- data definitions
- UI components
- business logic
Why Registration-Based Logic Helps
The registry pattern enables several advantages.
Reusable Validation
Validators can be reused across many forms.
Example:
user:passwordMatch
geo:coordinateValidator
payment:cardValidator
Reusable Workflows
Submission logic becomes reusable:
- API integration
- workflow orchestration
- event triggers
Domain-Specific Field Types
Custom fields can be registered once:
registerComponent("point2d", PointInput)
Any schema can use that type.
Dynamic Form Platforms
The architecture works well for:
- dynamic forms from APIs
- low-code platforms
- domain-specific applications
- large systems with many forms
When to Use Each Approach
Different libraries work best in different situations.
RJSF
Best for:
- simple JSON Schema forms
- rapid prototyping
JSON Forms
Best for:
- dynamic UI layouts
- rule-based behavior
Uniforms
Best for:
- projects using schema adapters
- strong design system integration
Form.io
Best for:
- full form platforms
- visual form builders
Formitiva
Best for:
- reusable form ecosystems
- dynamic form platforms
- domain-specific workflows
- large applications with many forms
Final Thoughts
Schema-driven forms are a powerful way to build dynamic user interfaces.
Libraries like RJSF, JSON Forms, Uniforms, and Form.io already separate form structure from UI rendering, making forms easier to maintain.
However, business logic is often still tied to components or form definitions.
A registry-based architecture pushes this separation further by treating validation, workflows, and UI components as independent, reusable modules.
This approach makes schema-driven forms not just a UI convenience, but a foundation for scalable form platforms.
Top comments (0)