Form schema validation
Form schema validation (스키마 검증)
Zod 스키마를 schemaResolver로 useForm의 검증 규칙으로 연결해 폼을 검증하는 방법을 다뤄요. 기본 필드, 중첩 필드, 목록 필드, 비동기 검증까지 스키마 기반 검증을 하나씩 설명해 드릴게요.
출처: 문서
본문
기본 필드 검증
import { z } from 'zod/v4';
import { useForm, schemaResolver } from '@mantine/form';
const schema = z.object({
name: z.string().min(2, { error: 'Name should have at least 2 letters' }),
email: z.email({ error: 'Invalid email' }),
age: z.number().min(18, { error: 'You must be at least 18 to create an account' }),
});
const form = useForm({
mode: 'uncontrolled',
initialValues: {
name: '',
email: '',
age: 16,
},
validate: schemaResolver(schema, { sync: true }),
});
form.validate();
form.errors;
// -> {
// name: 'Name should have at least 2 letters',
// email: 'Invalid email',
// age: 'You must be at least 18 to create an account'
// }
중첩 필드 검증
중첩된 객체 필드는 nested.field처럼 점(dot) 표기 경로로 오류가 저장돼요:
import { z } from 'zod/v4';
import { useForm, schemaResolver } from '@mantine/form';
const nestedSchema = z.object({
nested: z.object({
field: z.string().min(2, { error: 'Field should have at least 2 letters' }),
}),
});
const form = useForm({
mode: 'uncontrolled',
initialValues: {
nested: {
field: '',
},
},
validate: schemaResolver(nestedSchema, { sync: true }),
});
form.validate();
form.errors;
// -> {
// 'nested.field': 'Field should have at least 2 letters',
// }
목록 필드 검증
배열 필드는 list.0.name처럼 인덱스를 포함한 경로로 오류가 저장돼요:
import { z } from 'zod/v4';
import { useForm, schemaResolver } from '@mantine/form';
const listSchema = z.object({
list: z.array(
z.object({
name: z.string().min(2, { error: 'Name should have at least 2 letters' }),
})
),
});
const form = useForm({
mode: 'uncontrolled',
initialValues: {
list: [{ name: '' }],
},
validate: schemaResolver(listSchema, { sync: true }),
});
form.validate();
form.errors;
// -> {
// 'list.0.name': 'Name should have at least 2 letters',
// }
비동기 검증
스키마에 비동기 검사(예: API 호출로 이메일 중복 여부 확인)가 포함되어 있다면 { sync: true } 없이 schemaResolver를 사용해요. 이 경우 form.validate(), form.validateField(), form.isValid()는 Promise를 반환해요:
import { z } from 'zod/v4';
import { useForm, schemaResolver } from '@mantine/form';
const schema = z
.object({
email: z.email({ error: 'Invalid email' }),
})
.refine(
async (data) => {
const isTaken = await checkEmailExists(data.email);
return !isTaken;
},
{ error: 'Email is already taken', path: ['email'] }
);
const form = useForm({
mode: 'uncontrolled',
initialValues: { email: '' },
validate: schemaResolver(schema),
});
// form.validate() returns a Promise
await form.validate();
더 알아보기 (Learn more)
- Form validation — 폼 검증
- Form validators — 폼 검증자