Basic concepts
Learn the core concepts and principles behind Crustack Form to better understand how the library works.
defineForm
The defineForm function is the main entry point for creating a form. It takes three generic parameters:
FormValues: The type of the form values.SubmissionError: The type of the submission error, thrown/rejected byonSubmit.SubmissionData: The type of the submission data, returned/resolved byonSubmit.
It returns fully type-safe form components and hooks.
Example:
Root
The Root component provides the form context to its children and handles the form submission.
It expects:
- the
initialValuesthat should match theFormValuestype passed todefineForm. - the
onSubmitfunction that should either resolveSubmissionDataor rejectSubmissionError.
Optionally the Root component accepts a render prop pattern where the children prop can be a function that receives the form context, enabling direct access to form state and methods.
Example:
Form
Renders an accessible <form> element. The Root component can contain several Form components.
Example:
Field
The Field is the main building block of a form. It represents a single input field and its state.
A field is composed of a Control (the input itself), a Label, a Description and an ErrorMessage.
It expects:
- a
namethat should match a key of theFormValues - a
validatefunction that should return an error message if the field is invalid. - a
disabledprop that propagates the disabled state and ARIA attributes to all Field children, providing a more consistent accessibility experience than disabling individual controls
Example:
Managing the State
The state of the form can be managed using useFormCtx.
The state of a single field can be managed using useFieldCtx.
The state of a field array can be managed using useFieldArrayCtx.
useFormCtx can be used to read/write field values and touched states. The error state is read-only, managed by each field's validate function.
useFieldCtx reads the state of the closest parent Field component.
useFieldArrayCtx does the same as useFieldCtx but for field arrays.
Validation
Validation occurs automatically for all rendered fields that have a validate function.
This approach maintains consistency across the form and handles dependent field validation
without requiring additional configuration.
The validate prop can be a function or a Standard Schema.
The validation result appears in the ErrorMessage component when two conditions are met:
- The validate function returns an error message
- The field has been touched by the user
All fields are touched when a submit attempt is made.
Functional example:
Using zod:
The Root's onSubmit function is called when the form is submitted without errors.