Search for a command to run...
Last updated June 9, 2026
The useCtrovalidate hook is a headless form validation hook for React. It wraps ctrovalidate-core's validateAsync with reactive state management, stable callbacks, and automatic abort handling.
useCtrovalidate<T>(options)function useCtrovalidate<T extends object = object>(
options: UseCtrovalidateOptions<T>
): UseCtrovalidateReturn<T>UseCtrovalidateOptions<T>interface UseCtrovalidateOptions<T extends object> {
schema: ValidationSchema;
initialValues?: T;
validateOnBlur?: boolean;
customRules?: Record<string, RuleLogic | AsyncRuleLogic>;
aliases?: Record<string, SchemaRule>;
messages?: Record<string, string>;
locale?: string;
}| Option | Type | Default | Description |
|---|---|---|---|
schema | ValidationSchema | — | (Required) Field-to-rules mapping |
initialValues | T | {} | Initial form state |
validateOnBlur | boolean | true | When false, handleBlur updates dirty state without validating |
customRules | Record<string, RuleLogic | AsyncRuleLogic> | — | Custom rules merged over built-ins |
aliases | Record<string, SchemaRule> | — | Named rule combinations (merged with built-in aliases) |
messages | Record<string, string> | — | Custom error messages (passed to core's messages option) |
locale | string | — | Override locale for translator (core's i18n) |
UseCtrovalidateReturn<T>interface UseCtrovalidateReturn<T extends object> {
values: T;
errors: Partial<Record<keyof T, string>>;
isDirty: Partial<Record<keyof T, boolean>>;
isValidating: Partial<Record<keyof T, boolean>>;
handleChange: (name: keyof T, value: T[keyof T]) => void;
handleBlur: (name: keyof T) => void;
validateField: (name: keyof T, value?: T[keyof T]) => Promise<boolean>;
validateForm: () => Promise<boolean>;
reset: (newValues?: Partial<T>) => void;
}values: TCurrent form state. Updated by handleChange and reset.
errors: Partial<Record<keyof T, string>>Error messages for each field. undefined means the field is valid. Updated after each validateField or validateForm call.
isDirty: Partial<Record<keyof T, boolean>>Set to true when handleChange or handleBlur is called for a field. Remains true until reset.
isValidating: Partial<Record<keyof T, boolean>>Set to true during async validation. Use to show loading indicators:
<button disabled={isValidating.email}>
{isValidating.email ? 'Checking...' : 'Submit'}
</button>handleChange(name, value)Updates the field value, marks it dirty, and triggers validation immediately.
<input value={values.email} onChange={(e) => handleChange('email', e.target.value)} />handleBlur(name)Marks the field dirty. If validateOnBlur !== false, triggers validation.
<input onBlur={() => handleBlur('email')} />validateField(name, value?)Validates a single field. Uses the provided value or falls back to current state. Returns true if valid.
const isValid = await validateField('email');
const customValid = await validateField('email', 'test@example.com');validateForm()Validates all fields in the schema against current values. Returns true only if every field passes. Updates errors with all failures.
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (await validateForm()) {
// Submit
}
};reset(newValues?)Resets to initial form state. Clears all errors, dirty flags, and validating states. If newValues is provided, sets form to those values instead.
reset(); // Back to initial values
reset({ email: '' }); // Partial resetAll callbacks (handleChange, handleBlur, validateField, validateForm, reset) are wrapped in useCallback with zero dependencies using refs for latest values. They do not cause re-renders when passed as props.
Each field has its own AbortController. When handleChange or validateField is called while the field is still validating, the previous request is aborted. On unmount, all controllers are aborted.
// Internal behavior on handleChange('email', ...):
// 1. Abort previous email validation if in-flight
// 2. Create new AbortController
// 3. Call validateAsync with signal
// 4. If AbortError caught → returns false, no error displayedMessages are passed directly to validateAsync as the messages option. Core's priority chain applies:
messages['ruleName'] (from hook options)messages['*'] (wildcard)translator.translate(ruleName, params, locale)'Invalid input.' (hardcoded fallback)import type {
UseCtrovalidateOptions,
UseCtrovalidateReturn,
} from 'ctrovalidate-react';export * from './hooks/useCtrovalidate';Available imports:
| Import | Kind |
|---|---|
useCtrovalidate | Hook function |
UseCtrovalidateOptions | Type |
UseCtrovalidateReturn | Type |