@haloform/react
v0.2.0
Published
React adapter for haloform — useForm and useMultiStepForm hooks
Maintainers
Readme
This is the React adapter for haloform. It provides useForm and useMultiStepForm hooks powered by useSyncExternalStore over the core store.
Install
npm install @haloform/core @haloform/reactQuick Start
import { createForm, f } from "@haloform/core";
import { useForm } from "@haloform/react";
const loginSchema = createForm({
email: f.email({ required: true }),
password: f.text({ required: true, minLength: 8 }),
remember: f.checkbox({ default: false }),
});
function LoginForm() {
const { fields, handleSubmit, errors } = useForm(loginSchema);
return (
<form onSubmit={handleSubmit((values) => console.log(values))}>
<input
value={fields.email.value}
onChange={(e) => fields.email.onChange(e.target.value)}
onBlur={fields.email.onBlur}
/>
{fields.email.error && <span>{fields.email.error}</span>}
<input
type="password"
value={fields.password.value}
onChange={(e) => fields.password.onChange(e.target.value)}
onBlur={fields.password.onBlur}
/>
{fields.password.error && <span>{fields.password.error}</span>}
<label>
<input
type="checkbox"
checked={fields.remember.value}
onChange={(e) => fields.remember.onChange(e.target.checked)}
/>
Remember me
</label>
<button type="submit">Sign in</button>
</form>
);
}useForm(schema) Returns
| Property | Type | Description |
|---|---|---|
| fields | Record<name, FieldHandle> | Per-field state + onChange / onBlur |
| handleSubmit(fn) | (e?) => Promise<void> | Validates all, then calls fn(values) |
| isValid | boolean | true when no field has errors |
| isSubmitting | boolean | true while submit handler is running |
| errors | Record<name, string> | Current errors (only fields with errors) |
| reset() | void | Reset all fields to defaults |
| setValue(name, value) | void | Programmatically set a field |
| getValues() | InferFormValues<S> | Get all current values |
Multi-Step Forms
import { createMultiStepForm, f } from "@haloform/core";
import { useMultiStepForm } from "@haloform/react";
const checkoutSchema = createMultiStepForm([
{
name: "Shipping",
fields: {
name: f.text({ required: true }),
address: f.text({ required: true }),
},
},
{
name: "Payment",
fields: {
card: f.text({ required: true, pattern: /^\d{16}$/ }),
cvv: f.text({ required: true, minLength: 3 }),
},
},
]);
function Checkout() {
const {
fields,
currentStep,
currentStepName,
isLastStep,
nextStep,
prevStep,
handleSubmit,
} = useMultiStepForm(checkoutSchema);
return (
<div>
<h2>{currentStepName}</h2>
{currentStep === 0 && (
<>
<input value={fields.name.value} onChange={e => fields.name.onChange(e.target.value)} onBlur={fields.name.onBlur} />
<input value={fields.address.value} onChange={e => fields.address.onChange(e.target.value)} onBlur={fields.address.onBlur} />
</>
)}
{currentStep === 1 && (
<>
<input value={fields.card.value} onChange={e => fields.card.onChange(e.target.value)} onBlur={fields.card.onBlur} />
<input value={fields.cvv.value} onChange={e => fields.cvv.onChange(e.target.value)} onBlur={fields.cvv.onBlur} />
</>
)}
<button onClick={prevStep}>Back</button>
{isLastStep
? <button onClick={handleSubmit((v) => console.log(v))}>Submit</button>
: <button onClick={nextStep}>Next</button>
}
</div>
);
}useMultiStepForm(schema) Returns
Everything from useForm plus:
| Property | Type | Description |
|---|---|---|
| currentStep | number | Current step index (0-based) |
| currentStepName | string | Name of the current step |
| totalSteps | number | Total number of steps |
| isFirstStep / isLastStep | boolean | Position flags |
| nextStep() | Promise<boolean> | Validate current step, advance if valid |
| prevStep() | void | Go back (no validation) |
| goToStep(i) | void | Jump to step i |
Full Documentation
See the full documentation and examples on GitHub.
License
MIT — Made with care by Angel Orellana
