Troubleshooting
Common Issues and Solutions
Form Values Not Updating
Problem: Field values are not updating when changed.
Possible Causes and Solutions:
-
Missing onChange handler:
// ❌ Wrong - missing onChange
<Field
name="email"
render={({ value }) => (
<input value={value || ''} />
)}
/>
// ✅ Correct - include onChange
<Field
name="email"
render={({ value, onChange }) => (
<input
value={value || ''}
onChange={(e) => onChange(e.target.value)}
/>
)}
/>
-
Incorrect event handling:
// ❌ Wrong - passing event object
onChange={(e) => onChange(e)}
// ✅ Correct - extracting value
onChange={(e) => onChange(e.target.value)}
Validation Not Triggering
Problem: Rules are not being validated.
Possible Causes and Solutions:
-
Missing onBlur handler:
// ❌ Wrong - validation triggers on blur
<Field
name="email"
render={({ value, onChange }) => (
<input value={value || ''} onChange={(e) => onChange(e.target.value)} />
)}
>
<Rule validationFn={isRequired} message="Required" />
</Field>
// ✅ Correct - include onBlur
<Field
name="email"
render={({ value, onChange, onBlur }) => (
<input
value={value || ''}
onChange={(e) => onChange(e.target.value)}
onBlur={onBlur}
/>
)}
>
<Rule validationFn={isRequired} message="Required" />
</Field>
-
Incorrect validation function:
// ❌ Wrong - validation function has errors
const isRequired = (value) => {
return value !== undefined; // This allows empty strings
};
// ✅ Correct - proper validation
const isRequired = (value) => {
return value != null && value !== '';
};
TypeScript Errors
Problem: TypeScript compilation errors with form types.
Common Solutions:
-
Properly type your form interface:
// ❌ Wrong - using any
const form = useForm<any>();
// ✅ Correct - specific interface
interface MyForm {
email: string;
age: number;
}
const form = useForm<MyForm>();
-
Field name type safety:
// ❌ Wrong - hardcoded strings
const values = useOnChangeValues(form, ['nonexistentField']);
// ✅ Correct - only valid field names
const values = useOnChangeValues(form, ['email', 'age']);
Wizard Navigation Issues
Problem: Wizard steps not navigating correctly.
Possible Causes and Solutions:
-
Missing step registration:
// ❌ Wrong - step not wrapped in Step component
function MyStep() {
const { form } = useStepForm<WizardData, 'personal'>();
return (
<div>
<Field name="firstName" render={...} />
</div>
);
}
// ✅ Correct - wrapped in Step
function MyStep() {
const { form } = useStepForm<WizardData, 'personal'>();
return (
<Step name="personal">
<Field name="firstName" render={...} />
</Step>
);
}
-
Step validation blocking navigation:
// Check step validation logic
const validateStep = async (values) => {
console.log('Step validation:', values); // Debug output
return values?.requiredField != null;
};
<Step name="personal" onNext={validateStep}>
{/* Fields */}
</Step>
Performance Issues
Problem: Form re-renders too frequently.
Solutions:
-
Use specific field watching:
// ❌ Slow - watches all fields
const values = useOnChangeValues(form);
// ✅ Fast - watches only needed fields
const values = useOnChangeValues(form, ['email', 'name']);
-
Use onBlur for non-critical updates:
// For display purposes, use onBlur
const values = useOnBlurValues(form, ['firstName', 'lastName']);
-
Debounce expensive operations:
<Rule
validationFn={expensiveAsyncValidation}
message="Checking availability..."
isDebounced // This prevents rapid API calls
/>
Memory Leaks
Problem: Form contexts not cleaning up properly.
Solutions:
-
Proper component unmounting:
// Ensure forms are properly disposed when components unmount
useEffect(() => {
return () => {
// Form cleanup happens automatically
// But you can add custom cleanup if needed
};
}, []);
-
Avoid creating forms in render:
// ❌ Wrong - creates new form on every render
function MyComponent() {
const form = useForm(); // This should not be in render
return <Form form={form}>...</Form>;
}
// ✅ Correct - form created once
function MyComponent() {
const form = useForm(); // This is fine, hooks are stable
return <Form form={form}>...</Form>;
}
Debugging Tips
Enable Debug Logging
Add debug output to understand form behavior:
function DebugForm() {
const form = useFormContext<MyForm>();
const values = useOnChangeValues(form);
const validations = useValidations(form);
// Debug current state
console.log('Form values:', values);
console.log('Form validations:', validations);
return (
<div>
<pre>{JSON.stringify(values, null, 2)}</pre>
<pre>{JSON.stringify(validations, null, 2)}</pre>
</div>
);
}
Validation Debugging
const debugValidation = (value) => {
console.log('Validating value:', value);
const result = yourValidationLogic(value);
console.log('Validation result:', result);
return result;
};
<Rule validationFn={debugValidation} message="Debug rule" />
Step Debugging for Wizards
function WizardDebug() {
const wizard = useWizardContext<WizardData>();
return (
<div className="debug-panel">
<h4>Wizard Debug</h4>
<p>Current Step: {wizard.currentStep}</p>
<p>Is Last Step: {wizard.isLastStep.toString()}</p>
<p>Is First Step: {wizard.isFirstStep.toString()}</p>
<p>Is Step Ready: {wizard.isStepReady.toString()}</p>
<p>Steps: {wizard.steps.join(', ')}</p>
<pre>
{JSON.stringify(wizard.getValuesOfSteps(), null, 2)}
</pre>
</div>
);
}
Error Handling
Async Validation Errors
const safeAsyncValidation = async (value) => {
try {
const result = await apiCall(value);
return result.isValid;
} catch (error) {
console.error('Validation error:', error);
// Return true to allow form submission, or false to block
// depending on your error handling strategy
return true;
}
};
Form Submission Errors
function FormWithErrorHandling() {
const [submitError, setSubmitError] = useState<string | null>(null);
const form = useForm<MyForm>();
const handleSubmit = async () => {
try {
setSubmitError(null);
const values = form.getFormValues();
await submitData(values);
// Success handling
} catch (error) {
setSubmitError(error.message || 'Submission failed');
}
};
return (
<Form form={form} onSubmit={handleSubmit}>
{submitError && (
<div className="error-message">
{submitError}
</div>
)}
{/* Form fields */}
<button type="submit">Submit</button>
</Form>
);
}
Browser Compatibility
Supported Browsers
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
Common Browser Issues
-
Input events not firing: Some older browsers may not support certain input events. Use onChange
instead of onInput
for better compatibility.
-
Date input support: Date inputs may not be supported in older browsers. Consider using a date picker library as fallback.
Getting Help
If you're still experiencing issues:
- Check the examples - Look at the advanced examples for similar use cases
- Review the API documentation - Ensure you're using the correct types and patterns
- Create a minimal reproduction - Isolate the issue in a simple example
- Check browser console - Look for JavaScript errors or warnings
- File an issue - Report bugs on the GitHub repository with reproduction steps