Skip to main content

Typescript usage

This is a cheatsheet for using react-form-krafter with Typescript.

Register

src/components/fields/Register.tsx
import { lazy, type ComponentType } from "react";
import {
Register,
type RegisterComponent,
type RegisterFieldRenderProps,
type RegisterSettings,
} from "react-form-krafter";

type FieldsValue = number | string;

const COMPONENTS: RegisterComponent<FieldsValue>[] = [
{
type: "text",
render: lazy(() => import("./components/text")) as ComponentType<
RegisterFieldRenderProps<FieldsValue>
>,
},
{
type: "number",
render: lazy(() => import("./components/number")) as ComponentType<
RegisterFieldRenderProps<FieldsValue>
>,
},
];

const settings: RegisterSettings = {
labels: {
required: "This field is required",
},
};

function KrafterRegister({ children }: { children: React.ReactNode }) {
return (
<Register<FieldsValue> components={COMPONENTS} settings={settings}>
{children}
</Register>
);
}

Form

src/components/fields/Form.tsx
import { useRef } from "react";
import { Form, type Field, type FormApi } from "react-form-krafter";
import z from "zod";
import KrafterRegister from "~/components/internal/krafter/register";
import { Button } from "~/components/ui/button";

const SIGNUP_FIELDS: Field[] = [
{
name: "email",
label: "email.label",
placeholder: "email.placeholder",
required: true,
disabled: false,
type: "email",
initialValue: "",
wrapperClassName: "grid gap-3",
},
{
name: "password",
label: "password.label",
placeholder: "password.placeholder",
required: true,
disabled: false,
type: "password",
initialValue: "",
wrapperClassName: "grid gap-3",
},
{
name: "confirm_password",
label: "confirm_password.label",
placeholder: "confirm_password.placeholder",
required: true,
disabled: false,
type: "password",
initialValue: "",
wrapperClassName: "grid gap-3",
},
];

const schema = z.object({
email: z.email().min(1, "Email is required"),
password: z.string().min(6),
confirm_password: z.string().min(6),
});

type Schema = typeof schema;
type Validator = z.infer<Schema>;

function SignUp({ className, ...props }: React.ComponentProps<"div">) {
const formApi = useRef<FormApi<Validator> | null>(null);

return (
<KrafterRegister>
<Form<Validator, Schema>
formClassName="flex flex-col gap-6"
fields={SIGNUP_FIELDS}
schema={schema}
formApi={formApi}
onSubmit={async (data) => {
console.log(
data,
formApi.current?.fieldsInfo,
formApi.current?.fieldsInfo.errors
);

if (data.success) {
// Handle successful submission
} else {
// Handle failed submission
}
}}
onUpdate={(data) => {
if (formApi.current === null) return;

if (["password", "confirm_password"].includes(data.fieldName)) {
const isValid =
data.currentState.confirm_password === data.currentState.password;

formApi.current.setError(
"confirm_password",
isValid ? null : "Passwords do not match"
);
}
}}
>
<div className="flex flex-col gap-3">
<Button type="submit">Submit</Button>
</div>
</Form>
</KrafterRegister>
);
}