@conform-to/zod
Conform helpers for integrating with Zod
API Reference
getFieldsetConstraint
This tries to infer constraint of each field based on the zod schema. This is useful for:
- Making it easy to style input using CSS, e.g.
:required
- Having some basic validation working before/without JS
import { useForm } from '@conform-to/react';
import { getFieldsetConstraint } from '@conform-to/zod';
import { z } from 'zod';
const schema = z.object({
email: z.string({ required_error: 'Email is required' }),
password: z.string({ required_error: 'Password is required' }),
});
function Example() {
const [form, { email, password }] = useForm({
constraint: getFieldsetConstraint(schema),
});
}
parse
It parses the formData and returns a submission result with the validation error. If no error is found, the parsed data will also be populated as submission.value
.
import { useForm } from '@conform-to/react';
import { parse } from '@conform-to/zod';
import { z } from 'zod';
const schema = z.object({
email: z.string({ required_error: 'Email is required' }),
password: z.string({ required_error: 'Password is required' }),
});
function ExampleForm() {
const [form, { email, password }] = useForm({
onValidate({ formData }) {
return parse(formData, {
schema,
});
},
});
}
Or when parsing the formData on server side (e.g. Remix):
import { useForm } from '@conform-to/react';
import { parse } from '@conform-to/zod';
import { z } from 'zod';
const schema = z.object({
});
export async function action({ request }) {
const formData = await request.formData();
const submission = await parse(formData, {
schema: schema.refine(),
async: true,
});
if (!submission.value || submission.intent !== 'submit') {
return submission;
}
}
refine
A helper function to define a custom constraint on a superRefine check. This is mainly used to setup async validation.
import { refine } from '@conform-to/zod';
function createSchema(
intent: string,
constraints: {
// The validation will only be implemented on server side
isEmailUnique?: (email) => Promise<boolean>;
} = {},
) {
return z.object({
email: z
.string({ required_error: 'Email is required' })
.email('Email is invalid')
.pipe(
z.string().superRefine((email, ctx) =>
refine(ctx, {
validate: () => constraints.isEmailUnique?.(email),
when: intent === 'submit' || intent === 'validate/email',
message: 'Email is already used',
}),
),
),
});
}