@loydjs/react
v1.0.1
Published
Loyd react — native React hooks
Maintainers
Readme
Overview
@loydjs/react brings Loyd's schema validation into React with a minimal, type-safe form API. It uses the field dependency DAG from @loydjs/graph to revalidate only the fields that need it, making it efficient for large, complex forms.
No external form libraries required. No react-hook-form, no formik. Just Loyd schemas and React hooks.
Installation
npm install @loydjs/react @loydjs/graphRequires
@loydjs/core·@loydjs/schema·@loydjs/graph· React ≥ 18 · TypeScript ≥ 5.4
API
useForm(options)
The main hook. Returns register, handleSubmit, state, errors, and setValue.
import { useForm } from "@loydjs/react";
import { object, string, number } from "@loydjs/schema";
import type { Infer } from "@loydjs/types";
const SignupSchema = object({
name: string().minLength(2).maxLength(100),
email: string().email(),
age: number().int().min(18).max(120),
password: string().minLength(8),
});
type Signup = Infer<typeof SignupSchema>;
function SignupForm() {
const { register, handleSubmit, state, errors } = useForm<Signup>({
schema: SignupSchema,
defaultValues: { name: "", email: "", age: 18, password: "" },
mode: "onChange", // "onBlur" | "onSubmit" | "onChange"
});
const onValid = (data: Signup) => console.log("Submitted:", data);
const onInvalid = (issues) => console.log("Errors:", issues);
return (
<form onSubmit={handleSubmit(onValid, onInvalid)}>
<div>
<input {...register("name")} placeholder="Name" />
{errors.name && <p>{errors.name.message}</p>}
</div>
<div>
<input {...register("email")} type="email" placeholder="Email" />
{errors.email && <p>{errors.email.message}</p>}
</div>
<div>
<input {...register("age")} type="number" />
{errors.age && <p>{errors.age.message}</p>}
</div>
<div>
<input {...register("password")} type="password" placeholder="Password" />
{errors.password && <p>{errors.password.message}</p>}
</div>
<button type="submit" disabled={state.isSubmitting}>
{state.isSubmitting ? "Signing up..." : "Sign up"}
</button>
</form>
);
}useField(name, form)
Subscribes to a single field — re-renders only when that field changes.
import { useField } from "@loydjs/react";
function EmailField({ form }) {
const { value, error, onChange, onBlur } = useField("email", form);
return (
<div>
<input
value={value}
onChange={e => onChange(e.target.value)}
onBlur={onBlur}
type="email"
/>
{error && <span style={{ color: "red" }}>{error.message}</span>}
</div>
);
}useFieldArray(name, form)
Manages arrays of fields with append, remove, move, and swap.
import { useFieldArray } from "@loydjs/react";
const OrderSchema = object({
items: array(object({
productId: number().int().min(1),
quantity: number().int().min(1),
})),
});
function OrderForm() {
const form = useForm({ schema: OrderSchema, defaultValues: { items: [] } });
const { fields, append, remove } = useFieldArray("items", form);
return (
<form onSubmit={form.handleSubmit(onValid)}>
{fields.map((field, index) => (
<div key={field.id}>
<input {...form.register(`items.${index}.productId`)} type="number" />
<input {...form.register(`items.${index}.quantity`)} type="number" />
<button type="button" onClick={() => remove(index)}>Remove</button>
</div>
))}
<button type="button" onClick={() => append({ productId: 0, quantity: 1 })}>
Add item
</button>
<button type="submit">Place order</button>
</form>
);
}FormProvider + useFormContext
Share a form instance across a component tree without prop drilling.
import { FormProvider, useFormContext } from "@loydjs/react";
function App() {
const form = useForm({ schema: SignupSchema, defaultValues: { ... } });
return (
<FormProvider form={form}>
<PersonalInfoSection />
<AccountSection />
<SubmitButton />
</FormProvider>
);
}
function SubmitButton() {
const { state } = useFormContext();
return <button disabled={state.isSubmitting}>Submit</button>;
}Form state
interface FormState {
isSubmitting: boolean;
isValid: boolean;
isDirty: boolean;
submitCount: number;
touchedFields: Record<string, boolean>;
dirtyFields: Record<string, boolean>;
}Dependencies
| Package | Role |
|:---|:---|
| @loydjs/core | LoydSchema, LoydIssue types |
| @loydjs/schema | Schema definitions |
| @loydjs/graph | Field dependency DAG for incremental revalidation |
Peer dependencies
| Package | Version |
|:---|:---|
| react | ≥ 18.0.0 |
Documentation
License
MIT © b3nito404
