- Introduction
- Installation
- Quick Start Guide
- API Reference
- Architecture & Bundle Optimization
- Migration Guide
- Examples
- TypeScript Support
- React Compatibility
- Performance
The React Form Builder is a powerful, configuration-first library for building complex forms in React 17+ applications. The library has been refactored to prioritize form configuration generation over component rendering, making it lightweight, framework-agnostic at its core, and optimized for modern development workflows.
Key Features:
- Configuration-First Architecture: Generate form configurations that work with any UI framework or custom components
- Optional UI Components: Import rendering components only when needed for optimal bundle sizes
- React 17+ Compatible: Full support for React 17 and later versions
- Schema-Driven: Define your entire form structure, including fields, types, and validation, with a declarative
FormModel - Lightweight Core: Use just the configuration engine without React dependencies
- Tree-Shakeable: Import only the functionality you need
- Powerful Hooks: Choose between
useFormConfig(new) oruseForm(backward compatible) - Dynamic Fields: Conditionally show, hide, disable, or modify fields based on the values of other fields
- Extensible Plugins: Register custom field types, validation rules, or rendering overrides to extend core functionality
- Analytics & Event Hooks: Built-in event bus and callbacks for form lifecycle events
- Multiple Entry Points: Import from core, UI, or full library based on your needs
Install the package using your favorite package manager:
NPM
npm install @dynamic_forms/reactYarn
yarn add @dynamic_forms/reactPeer Dependencies
The library supports React 17+ and has optional peer dependencies:
# Required for React hooks and UI components
npm install react@>=17.0.0 react-dom@>=17.0.0
# Optional for TypeScript projects
npm install @types/react @types/react-domNote: React dependencies are optional when using only the core configuration functionality.
The library offers three usage patterns depending on your needs:
Perfect for custom UI frameworks or minimal bundle sizes:
import { createFormConfig } from '@dynamic_forms/react';
// Define your form model
const userProfileModel = [
{
key: 'fullName',
type: 'text',
label: 'Full Name',
validators: { required: true, min: 2 },
},
{
key: 'email',
type: 'text',
label: 'Email Address',
validators: { required: true, pattern: /^\S+@\S+\.\S+$/ },
},
];
// Generate configuration (works without React)
const configResult = createFormConfig(userProfileModel, {
initialValues: { fullName: '', email: '' },
enableDependencies: true,
enableValidation: true,
});
// Use with your custom UI components
console.log('Fields:', configResult.fields);
console.log('Validation:', configResult.validation);Use React state management with your own components:
import { useFormConfig } from '@dynamic_forms/react';
function MyCustomForm() {
const form = useFormConfig(userProfileModel, {
initialValues: { fullName: '', email: '' }
});
return (
<form onSubmit={form.handleSubmit(onSubmit)}>
{form.fields
.filter(field => form.isFieldVisible(field.path))
.map(field => (
<MyCustomInput
key={field.path}
field={field}
value={form.values[field.path]}
onChange={(value) => form.setValue(field.path, value)}
error={form.errors[field.path]}
/>
))}
<button type="submit">Submit</button>
</form>
);
}Use the complete library with built-in components:
import { useFormConfig } from '@dynamic_forms/react';
import { FormRenderer } from '@dynamic_forms/react/ui';
function UserProfileForm() {
const form = useFormConfig(userProfileModel, {
initialValues: { fullName: 'John Doe', email: '' }
});
const handleSubmit = async (values) => {
console.log('Form Submitted:', values);
// await api.save(values);
};
return (
<form onSubmit={form.handleSubmit(handleSubmit)}>
<FormRenderer form={form} config={form.config} />
<button type="submit">Save Profile</button>
</form>
);
}The library provides multiple entry points for different use cases:
// Core functionality (always available)
import { createFormConfig, useFormConfig } from '@dynamic_forms/react';
// UI components (optional, tree-shakeable)
import { FormRenderer } from '@dynamic_forms/react/ui';
// Everything together (backward compatibility)
import { useForm, FormRenderer } from '@dynamic_forms/react/full';Generates form configuration without React dependencies. Perfect for server-side rendering or non-React environments.
Parameters:
model:FormModel- The form schema definitionoptions:FormConfigOptions(optional)flags:Record<string, boolean>- Feature flags for conditional fieldsinitialValues:FormValues- Initial form valuesenableDependencies:boolean- Enable dependency resolution (default: true)enableValidation:boolean- Enable validation rules (default: true)
Returns: FormConfigResult
config: Complete form configurationfields: Array of processed field configurationslookup: Field lookup map by pathdependencies: Dependency resolution mapvalidation: Validation utilitiesstate: Field state query functions
import { createFormConfig } from '@dynamic_forms/react';
const result = createFormConfig(formModel, {
initialValues: { name: '', email: '' },
enableDependencies: true,
});React hook for form state management with the new architecture.
Parameters:
model:FormModel- The form schema definitionoptions:UseFormConfigOptions(optional)- All
FormConfigOptionsplus: formId:string- Unique form identifier for analyticsenableAnalytics:boolean- Enable event trackingeventHooks:EventHooks- Lifecycle event callbacks
- All
Returns: UseFormConfigReturn
- All
FormConfigResultproperties plus: values: Current form valueserrors: Validation errorstouched: Touched field statesdynamicOptions: Resolved dynamic options- State management functions (
setValue,setTouched, etc.) - Event handlers (
handleChange,handleBlur, etc.) - Form actions (
handleSubmit,triggerValidation, etc.)
import { useFormConfig } from '@dynamic_forms/react';
const form = useFormConfig(formModel, {
initialValues: { name: '', email: '' },
formId: 'user-profile',
eventHooks: {
onFieldChange: (path, value) => console.log(`${path} changed`),
},
});The original hook, now enhanced to work with the new architecture while maintaining full backward compatibility.
Parameters: Same as useFormConfig
Returns: UseFormReturn - Same interface as before
import { useForm } from '@dynamic_forms/react';
// Works exactly as before
const form = useForm(formModel, { initialValues });Import from @dynamic_forms/react/ui for optional rendering components:
Props:
form: Form object fromuseFormConfigoruseFormconfig: Form configuration (available asform.config)renderers: Custom field type rendererscustomRenderers: Named custom renderers
import { FormRenderer } from '@dynamic_forms/react/ui';
<FormRenderer form={form} config={form.config} />Individual field renderers available for custom usage:
TextInput,NumberInput,Dropdown,DatePicker,CheckboxInput,ArrayFieldWrapper
The FormModel is an array of FieldProps objects that defines the form schema.
FieldProps Interface:
| Property | Type | Description |
|---|---|---|
key |
string |
Required. The unique identifier and key for the field's value in the form state. |
type |
'text' | 'number' | 'select' | 'date' | 'array' | 'checkbox' |
Required. The type of field to render. |
label |
string |
Required. The display label for the form field. |
validators |
object |
Validation rules for the field. See Validators section below. |
layout |
object |
Grid layout properties: row, col, rowSpan, colSpan, className. |
disabled |
boolean |
If true, the field is disabled. Can be overridden by the dependencies engine. |
hidden |
boolean |
If true, the field is not rendered. Can be overridden by the dependencies engine. |
options |
() => Promise<Array<{value, label}>> |
A function that returns a promise resolving to an array of options for a select field. |
dynamicOptions |
object |
Load select options dynamically based on other field values. See Dynamic Options. |
dependencies |
Array<object> |
Rules to dynamically modify this field based on another field's value. See Dependencies. |
itemModel |
FormModel |
For fields of type: 'array', this defines the schema for each item in the array. |
renderer |
string |
A key to map this field to a custom renderer passed to FormRenderer. |
meta |
Record<string, any> |
An object for arbitrary annotations (e.g., analytics IDs). |
flags |
Record<string, boolean> |
A map of feature flags; the field is only included if all flags are true. |
Validators:
The validators object supports the following keys:
required, min, max, minItems, maxItems, pattern: RegExp, custom: (value) => string[], decimal_places.
Dependencies:
The dependencies object connects field properties to the state of other fields. The system supports both single-field and multi-field dependencies using a unified approach.
Dependency Format:
{ fields: string[], condition: (watchedValues, formValues) => boolean, overrides: Partial<FieldProps> }
fields: An array of fieldkeys to watch (use["singleField"]for single-field dependencies)condition: A function that receives watched values (only the specified fields) and all form values, returningtrueif the override should be appliedoverrides: An object withFieldPropsto apply when the condition is met
Examples:
// Single-field dependency
{
key: 'conditionalField',
type: 'text',
label: 'Conditional Field',
hidden: true,
dependencies: {
fields: ['showField'],
condition: (watchedValues) => watchedValues.showField === true,
overrides: { hidden: false }
}
}
// Multi-field dependency
{
key: 'adminPanel',
type: 'text',
label: 'Admin Panel',
hidden: true,
dependencies: {
fields: ['userRole', 'isActive'],
condition: (watchedValues) => {
return watchedValues.userRole === 'admin' && watchedValues.isActive === true;
},
overrides: { hidden: false }
}
}Dynamic Options:
{ trigger: string[], loader: (values) => Promise<Array<{value, label}>> }
trigger: An array of fieldkeys that should trigger a reload of the options.loader: A function that receives the entire form'svaluesobject and returns the new options.
Import from @dynamic_forms/react/ui for optional providers:
<FormProvider>: Provides internationalization context.- Props:
locale: string,messages: Record<string, string>.
- Props:
<AnalyticsProvider>: Provides an event handler for analytics.- Props:
onEvent: (name, data) => void.
- Props:
<FormWrapper>: A simple layout component.- Props:
title: string,loading?: boolean.
- Props:
The library includes a plugin system to extend its core functionality.
FormPlugin Interface:
name: string: A unique name for the plugin.extendConfig?(model, config): A function to modify theFormConfig.onValidate?(field, value): A function to add custom validation rules.renderField?(field, form): A function to render a field, overriding the default renderer.
Use registerPlugin(plugin) to add a plugin and unregisterPlugin(name) to remove it.
The library provides three entry points for different use cases:
// Main entry point - Core functionality only
import { createFormConfig, useFormConfig } from '@dynamic_forms/react';
// UI entry point - Optional rendering components
import { FormRenderer } from '@dynamic_forms/react/ui';
// Full entry point - Everything together (backward compatibility)
import { useForm, FormRenderer } from '@dynamic_forms/react/full';| Import Pattern | Bundle Impact | Use Case |
|---|---|---|
| Core only | ~15KB | Configuration generation, custom UI |
| Core + UI | ~45KB | Full featured forms with built-in components |
| Full library | ~45KB | Backward compatibility, gradual migration |
The library is optimized for tree shaking:
// Only includes createFormConfig and dependencies
import { createFormConfig } from '@dynamic_forms/react';
// Only includes useFormConfig and React dependencies
import { useFormConfig } from '@dynamic_forms/react';
// Only includes specific UI components
import { TextInput, Dropdown } from '@dynamic_forms/react/ui';/src
/core # Core configuration logic (framework-agnostic)
/config # Form configuration generation
/validation # Field validation utilities
/dependencies # Dependency resolution
/state # State management utilities
/types # Core type definitions
/hooks # React hooks (minimal React dependency)
/ui # Optional UI components (tree-shakeable)
/renderers # Individual field renderers
/providers # Optional React providers
/plugins # Plugin system
/events # Event system
/model # Form model interfaces
/types # Shared TypeScript types
/utils # Shared utilities
index.ts # Main entry point (core-first)
ui.ts # UI components entry point
full.ts # Complete library entry point
β No Breaking Changes - Your existing code continues to work without modifications:
// This still works exactly as before
import { useForm, FormRenderer } from '@dynamic_forms/react';
const form = useForm(formModel, { initialValues });- No Migration Required: Keep using existing patterns
- Gradual Migration: Adopt new patterns for new forms
- Full Migration: Optimize all forms for better performance
Before (still supported):
import { useForm, FormRenderer } from '@dynamic_forms/react';
const form = useForm(formModel, { initialValues });After (recommended):
import { useFormConfig } from '@dynamic_forms/react';
import { FormRenderer } from '@dynamic_forms/react/ui';
const form = useFormConfig(formModel, { initialValues });For comprehensive migration instructions, examples, and troubleshooting, see:
The migration guide covers:
- Detailed migration strategies
- Bundle size optimization
- TypeScript migration
- Performance improvements
- Common issues and solutions
- Testing migration
- Migration checklist
The library includes comprehensive examples demonstrating different usage patterns:
- Core Configuration Only: Minimal bundle, custom UI components
- New Architecture with UI: Using
useFormConfigwith built-in components - Backward Compatibility: Using existing
useFormpatterns - Advanced Features: Dependencies, validation, dynamic options, analytics
Run the examples:
npm run examples:serveThe library is built with TypeScript and provides comprehensive type definitions:
import type {
FormModel,
FieldProps,
UseFormConfigReturn,
FormConfigResult,
ValidationRule,
DependencyResolution,
} from '@dynamic_forms/react';All entry points include proper TypeScript definitions with full IntelliSense support.
- React 17+: Full support for React 17 and later versions
- React 18: Optimized for React 18 features
- Server-Side Rendering: Core functionality works without React
- Concurrent Features: Compatible with React 18 concurrent features
The refactored architecture provides significant performance improvements:
- Smaller bundles: Import only what you need
- Faster initialization: Optimized configuration generation
- Better tree shaking: Unused code is eliminated
- Reduced re-renders: Improved state management
Run performance tests:
npm run perf:testFor detailed API documentation, see π API Reference
// Core functionality only (minimal bundle)
import { createFormConfig, useFormConfig } from '@dynamic_forms/react';
// UI components (optional)
import { FormRenderer } from '@dynamic_forms/react/ui';
// Backward compatibility (everything)
import { useForm, FormRenderer } from '@dynamic_forms/react/full';// Configuration-first approach
const form = useFormConfig(formModel, { initialValues });
// With UI components
<FormRenderer form={form} config={form.config} />
// Custom UI
{form.fields.map(field => (
<MyInput
key={field.path}
field={field}
value={form.values[field.path]}
onChange={(value) => form.setValue(field.path, value)}
/>
))}| Import Pattern | Size | Use Case |
|---|---|---|
| Core only | ~15KB | Custom UI, server-side |
| Core + UI | ~45KB | Full-featured forms |
| Full library | ~45KB | Backward compatibility |
We welcome contributions! Please see our Contributing Guide for details.
This project is licensed under the ISC License - see the LICENSE file for details.
- π Documentation
- π Examples
- π Issues
- π¬ Discussions