Internals: Component Rendering & Registry
This document explains the internal mechanics of how FieldRenderer dispatches JSON definitions to React components. For the getting-started guide on building and registering your own components, see Basic Usage ā ComponentRegistry.
1. The Dispatcher Layer
The FieldRenderer acts as the dispatcher. It receives a field definition and decides which React component to render.
The Resolution Process:
- Extract State: Calculates
computedState(visible, disabled, required). - Lookup: Retrieves the component from
ComponentRegistryContextusingfield.typeas the key. - Validate: If the type is not mapped, it renders a fallback UI to inform the developer.
2. Dependency Watching (Performance)
To ensure high performance in forms with hundreds of fields, FieldRenderer uses Selective Watching.
const dependencies = useMemo(() => extractFieldDependencies(field), [field]); const dependencyValues = useWatch({ control, name: dependencies.length > 0 ? dependencies : ["__ROOT_WATCH__"], });
- Benefit: Re-renders only happen when a field that this specific field actually depends on changes.
- Complexity: Reducing global re-renders from O(N) to O(1) for the vast majority of user interactions.
3. The Adapter Interface
Every component in the registry must follow the Adapter Interface. The engine passes the following props:
field: The final field definition (including computed labels and required status).computedState: The raw result from the rule engine.apiOptions: Normalised options if the field has adataSource.isApiLoading: Loading state for async data sources.
4. Infinite Loop Protection
The dispatcher implements a safeguard against circular computed value dependencies.
- Threshold: The engine checks if a field's value has been updated 6 or more times in a single execution tick.
- Action: If the threshold is exceeded, the engine halts the update and logs a console error to prevent browser freezing.
5. Memoization Strategy
FieldRenderer is wrapped in React.memo using the default shallow comparison. Since it depends on useWatch, the component itself only re-renders when the specific dependencies change, keeping the Virtual DOM lean.
6. Setting Up the ComponentRegistry
For a step-by-step guide on creating adapter components, building the registry object, and injecting it into your app, see:
š Basic Usage ā Section 4: ComponentRegistry
This section is intentionally kept in the Getting Started guide because the registry is a required part of any DFBE integration ā not an advanced concern.
7. Step Component Registry (StepComponentRegistry)
Similar to how FieldRenderer dispatches fields, the form engine supports a StepComponentRegistry for CustomStep types.
- Lookup: When
currentStep.type === "custom", the host application is responsible for looking up the component in theStepRegistryContext. - Interface: Custom step components receive
step: CustomStepas props. - Navigation Control: Unlike standard fields, custom steps use
setStepGuardto control navigation flow.
For more details on implementing custom steps, see Custom Steps Guide.