Hooks
The package provides hooks for accessing form state and building custom components.
useFormEngine
Access the form engine context:
import { useFormEngine } from '@schema-engine/forms-react';
function MyComponent() {
const { engine, executeAction } = useFormEngine();
const inputElement = engine.getElement('input');
const allElements = engine.getAllElements();
return <div>{/* ... */}</div>;
}useFormInstance
Access the React Hook Form instance directly:
import { useFormInstance } from '@schema-engine/forms-react';
function MyComponent() {
const form = useFormInstance();
const { getValues, setValue, trigger, formState } = form;
const currentValues = getValues();
const { errors, isDirty, isValid } = formState;
return <div>{/* ... */}</div>;
}useFormInstanceActions
Access form actions and step navigation:
import { useFormInstanceActions } from '@schema-engine/forms-react';
function StepNavigation() {
const {
currentStep,
totalSteps,
goToStep,
goToNext,
goToPrevious,
navigation,
dispatchTrigger,
} = useFormInstanceActions();
return (
<div>
<span>Step {currentStep + 1} of {totalSteps}</span>
<button
onClick={goToPrevious}
disabled={!navigation.canGoPrevious}
>
Back
</button>
<button
onClick={goToNext}
disabled={!navigation.canGoNext}
>
{navigation.isLastStep ? 'Submit' : 'Next'}
</button>
</div>
);
}FormInstanceContextValue
interface FormInstanceContextValue {
currentStep: number;
totalSteps: number;
goToStep: (step: number) => void;
goToNext: () => void;
goToPrevious: () => void;
stepStates?: {
completed: boolean[];
valid: boolean[];
visited: boolean[];
};
navigation: {
canGoNext: boolean;
canGoPrevious: boolean;
isFirstStep: boolean;
isLastStep: boolean;
goToStep: (step: number) => void;
goToNextStep: () => void;
goToPreviousStep: () => void;
};
dispatchTrigger: (trigger: FormActionTrigger, extraMetadata?: Record<string, unknown>) => Promise<ActionExecutionResult[]>;
dispatchTriggerSync: (trigger: FormActionTrigger, extraMetadata?: Record<string, unknown>) => void;
}useControlledFormElement
Build custom field components with full form integration:
import { useControlledFormElement } from '@schema-engine/forms-react';
function CustomInput(config: FormEngine.ElementConfig) {
const {
field,
fieldState,
value,
error,
isRequired,
onChange,
onBlur,
fieldProps,
labelProps,
errorProps,
containerStyles,
} = useControlledFormElement(config);
return (
<div style={containerStyles}>
<label {...labelProps}>{config.label}</label>
<input
{...fieldProps}
value={value || ''}
onChange={(e) => onChange(e.target.value)}
onBlur={onBlur}
/>
{errorProps && <span {...errorProps}>{error}</span>}
</div>
);
}Return Value
interface UseControlledFormElementReturn {
field: ControllerRenderProps;
fieldState: ControllerFieldState;
formState: UseFormStateReturn;
value: any;
error: string | undefined;
isDirty: boolean;
isTouched: boolean;
isRequired: boolean;
onChange: (value: any) => void;
onBlur: () => void;
fieldProps: object;
labelProps: object;
errorProps: object | null;
containerStyles: object;
gridStyles: object;
config: FormEngine.ElementConfig;
combineHandlers: <T>(controllerHandler: (value: T) => void, propsHandler?: (value: T) => void) => (value: T) => void;
}useActionDispatcher
Get an ActionDispatcher instance for executing actions:
import { useFormEngine, useActionDispatcher } from '@schema-engine/forms-react';
function MyComponent() {
const { engine } = useFormEngine();
const dispatcher = useActionDispatcher(engine);
const handleClick = async () => {
const results = await dispatcher.dispatch('form_submit', context);
console.log(results);
};
return <button onClick={handleClick}>Submit</button>;
}useConstraintLogic
Evaluate constraint logic for conditional visibility/disabled/required states:
import { useConstraintLogic } from '@schema-engine/forms-react';
function ConditionalField({ constraints, baseRequired, fieldPath }) {
const result = useConstraintLogic(constraints, baseRequired, fieldPath);
if (!result.isVisible) {
return null;
}
return (
<input
disabled={result.isDisabled}
required={result.isRequired}
/>
);
}Return Value
interface ConstraintEvaluationResult {
isVisible: boolean;
isDisabled: boolean;
isRequired: boolean;
}useGDPRConsent
Manage GDPR consent state:
import { useGDPRConsent } from '@schema-engine/forms-react';
function ConsentStatus() {
const consent = useGDPRConsent();
return (
<div>
<p>Has consent: {consent.hasConsent() ? 'Yes' : 'No'}</p>
<button onClick={consent.grantConsent}>Accept</button>
<button onClick={consent.revokeConsent}>Decline</button>
</div>
);
}Return Value
{
hasConsent: () => boolean;
grantConsent: () => void;
revokeConsent: () => void;
needsUpdate: () => boolean;
getConsent: () => ConsentData;
}useGTMTracker
Integrate with Google Tag Manager:
import { useGTMTracker } from '@schema-engine/forms-react';
function MyForm() {
const gtm = useGTMTracker();
const handleSubmit = () => {
gtm.pushFormEvent('form_submit', formData, { formId: 'contact' });
};
return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}Return Value
{
isAvailable: () => boolean;
push: (event: string, data?: Record<string, any>) => void;
pushFormEvent: (
eventType: 'form_mount' | 'form_step_complete' | 'form_submit' | 'form_abandon',
formData?: Record<string, any>,
metadata?: Record<string, any>
) => void;
initialize: (containerId: string) => void;
}