A React library built on top of react-hook-form that turns schema definitions into dynamic forms, reducing boilerplate and simplifying validation while maintaining full customizability.
⚠️ CAUTION: This project is under active development. The API may change without notice.
While React Hook Form provides an excellent foundation for handling forms in React applications with uncontrolled components and high performance, it comes with certain limitations:
- Requires repetitive code for defining fields and validation rules
- Complex forms with nested structures become verbose and harder to maintain
- Form structure is tightly coupled with UI components
- No standardized way to define form schemas separate from UI
Schema Form addresses these limitations by:
- Separating Concerns - Define your form structure and validation rules in one place as a schema, keeping them separate from UI components
- Reducing Boilerplate - Convert concise schema definitions into fully functional forms without repetitive code
- Enhancing Type Safety - Leverage TypeScript to ensure your form data structure matches your schema definition
- Maintaining Flexibility - Access all the power of React Hook Form while adding schema-driven development
- Simplifying Complex Forms - Handle nested objects, arrays, and conditional fields with structured schemas rather than imperative code
Schema Form doesn't replace React Hook Form - it enhances it with a declarative, schema-driven approach while preserving all its performance benefits.
npm install @basestacks/schema-formimport { SchemaForm, FormFields } from "@basestacks/schema-form";
interface FormValues {
username: string;
password: string;
rememberMe: boolean;
}
const fields: FormFields<FormValues> = {
username: {
type: "text",
title: "Username",
placeholder: "Enter your username",
required: true,
minLength: 6,
maxLength: 32,
pattern: {
value: /^\w+$/,
message: "Username can only contain letters, numbers and underscores",
},
},
password: {
type: "text",
title: "Password",
placeholder: "••••••••",
required: true,
minLength: 6,
renderContext: {
secureTextEntry: true,
},
},
rememberMe: {
type: "checkbox",
title: "Remember me",
},
};
export function LoginForm() {
const handleSubmit = (data: FormValues) => {
console.log("Form data:", data);
};
return (
<SchemaForm
fields={fields}
onSubmit={handleSubmit}
{/** Additional props for react-hook-form */}
shouldUseNativeValidation={true}
/>
);
}That's it! The form will render with proper validation. For UI components, see the detailed section below.
Create custom field components and a form layout to override the default UI:
import * as React from "react";
import {
useField,
SchemaFormProvider,
SchemaFormRenderProps,
} from "@basestacks/schema-form";
export interface RenderContext {
readonly secureTextEntry?: boolean;
readonly submitLabel?: string;
}
export function FormProvider({ children }: React.PropsWithChildren) {
return (
<SchemaFormProvider
components={{
Form: FormLayout,
fields: {
text: TextField,
checkbox: CheckboxField
},
}}
>
{children}
</SchemaFormProvider>
);
}
function FormLayout({
form,
onSubmit,
children,
renderContext,
}: SchemaFormRenderProps<RenderContext>) {
return (
<form onSubmit={form.handleSubmit(onSubmit)}>
{children}
<button type="submit">{renderContext?.submitLabel ?? "Submit"}</button>
</form>
);
}
function TextField() {
const { field, name, placeholder, title, renderContext } = useField();
return (
<div className="field">
<label htmlFor={name}>{title}</label>
<input
type={renderContext.secureTextEntry ? "password" : "text"}
placeholder={placeholder}
{...field}
/>
</div>
);
}
function CheckboxField() {
const { field, name, title } = useField();
return (
<div className="field">
<div>
<input type="checkbox" {...field} />{" "}
<label htmlFor={name}>{title}</label>
</div>
</div>
);Wrap your form with the FormProvider to apply custom UI components and context data:
<FormProvider>
<LoginForm />
</FormProvider>Check out the example for a complete implementation.
We welcome contributions to make @basestacks/schema-form even better! Whether you're fixing bugs, improving documentation, or adding new features, your help is appreciated.
- Node.js 20
- pnpm v9
For detailed contribution guidelines, please read our CONTRIBUTING.md document.