关于 mantine-form
面向 Mantine 9.x 的技能,介绍如何使用 `@mantine/form` 构建表单,涵盖输入绑定、验证策略、受控与非受控模式,以及复杂表单行为。
主要功能
- 01非受控与受控表单模式
- 02输入属性与字段绑定
- 03规则、模式和函数验证
- 04提交、变更或失焦时验证
- 05值监听与重新渲染行为
适用场景
- 01使用 Mantine 输入组件构建表单
- 02通过模式验证字段
- 03减少输入时的重新渲染
- 04构建条件式或嵌套表单
MCP 相关
当随附参考资料无法解答问题时,建议查阅 Mantine MCP 服务的文档。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mantinedev/ skills --skill mantine-form安装后在 Claude Code 中输入/mantine-form确认已加载。
附带文件references/api.mdreferences/patterns.md
详细介绍
Mantine Form 技能
适用于 Mantine 9.x。
核心工作流
1. 设置表单
对于所有表单,推荐使用非受控模式。默认模式为 'controlled',因此请显式设置。
const form = useForm({
mode: 'uncontrolled',
initialValues: {
email: '',
age: 0,
},
validate: {
email: isEmail('Invalid email'),
age: isInRange({ min: 18 }, 'Must be at least 18'),
},
});
2. 使用 getInputProps 连接输入组件
在非受控模式下,每个输入组件都需要 key={form.key('path')}。如果没有它,在调用 form.setFieldValue、form.setValues 或 form.reset 后,输入组件不会更新。
<TextInput label="Email" key={form.key('email')} {...form.getInputProps('email')} />
<NumberInput label="Age" key={form.key('age')} {...form.getInputProps('age')} />
复选框和开关需要 { type: 'checkbox' }:
<Checkbox
label="I agree"
key={form.key('agreed')}
{...form.getInputProps('agreed', { type: 'checkbox' })}
/>
Select、NumberInput、Radio.Group、Checkbox.Group 及其他使用 value / onChange 配对的 Mantine 输入组件,可以使用普通的 getInputProps 和 key:
<Radio.Group label="Delivery" key={form.key('delivery')} {...form.getInputProps('delivery')}>
<Radio value="standard" label="Standard" />
<Radio value="express" label="Express" />
</Radio.Group>
对于没有 Radio.Group 的独立单选按钮,请使用 form.getInputProps('color', { type: 'radio', value: 'red' }),并为每个单选按钮添加 key={form.key('color')}。
对于没有 error 属性的组件(Slider、RangeSlider、Rating、SegmentedControl、Chip.Group),需要使用 { withError: false },并自行渲染错误信息:
<Slider key={form.key('stock')} {...form.getInputProps('stock', { withError: false })} />
{form.errors.stock && <Text c="red" size="sm">{form.errors.stock}</Text>}
3. 处理提交
<form onSubmit={form.onSubmit((values) => console.log(values))}>
...
<Button type="submit">Submit</Button>
</form>
只有在验证通过时,onSubmit 才会调用处理函数。如果处理函数返回 Promise,则在 Promise 完成前,form.submitting 都为 true。处理失败的方式:
form.onSubmit(
(values, event) => save(values),
(errors, values, event) => console.log('Validation failed', errors) // { 'user.email': 'Invalid email' }
);
验证
规则对象(最常见)
validate: {
name: isNotEmpty('Required'),
email: isEmail('Invalid email'),
password: hasLength({ min: 8 }, 'Min 8 chars'),
confirmPassword: matchesField('password', 'Passwords do not match'),
}
Schema(zod、valibot、arktype 及其他 Standard Schema 库)
import { z } from 'zod/v4';
import { schemaResolver, useForm } from '@mantine/form';
const schema = z.object({
email: z.email({ error: 'Invalid email' }),
age: z.number().min(18, { error: 'Must be at least 18' }),
});
const form = useForm({
mode: 'uncontrolled',
initialValues: { email: '', age: 0 },
validate: schemaResolver(schema, { sync: true }),
});
schemaResolver 内置其中,无需安装解析器包。对于同步 Schema,请传入 { sync: true },这样 form.validate() 会返回普通结果,而不是 Promise。
函数(用于跨字段逻辑)
validate: (values) => ({
endDate: values.endDate < values.startDate ? 'End must be after start' : null,
});
何时验证
默认情况下,仅在提交时验证字段。
validateInputOnChange: true, // also validate every field when it changes
validateInputOnChange: ['email'], // only the listed fields
validateInputOnBlur: ['email'], // same options, on blur
validateInputOnBlur: [`members.${FORM_INDEX}.email`], // list items, FORM_INDEX is exported from @mantine/form
启用失焦验证后,用户点击提交按钮时出现的错误会导致布局移动,点击可能无法命中按钮。请将提交按钮放在错误出现时不会移动的位置(例如,固定位置的页脚),或者改为在值变化时验证。
模式
'uncontrolled'(推荐) | 'controlled'(默认) | |
|---|---|---|
| 值的存储位置 | Ref | React 状态 |
form.values | 不会更新,请使用 form.getValues() | 每次变化时更新 |
| 值变化时重新渲染 | 否 | 是 |
| 输入属性 | defaultValue + onChange | value + onChange |
输入组件上的 key={form.key(path)} | 必需 | 不需要 |
非受控模式下哪些内容会重新渲染
- 在输入组件中输入内容不会导致表单重新渲染。
- 渲染期间调用的
form.getValues()不会随输入内容更新。若要根据某个值显示或隐藏部分表单,请使用form.useWatchValue(path)。支持嵌套路径:form.useWatchValue('members.0.role')。 setFieldValue、setValues、insertListItem、removeListItem、reorderListItem、reset和initialize会导致重新渲染,因此从form.getValues().items.map(...)渲染列表是正确的。- 在两种模式下,渲染期间都可以使用
form.errors、form.isDirty()、form.isDirty('path')、form.isTouched()、form.submitting和form.validating:它们变化时表单会重新渲染。
const shipsInternationally = form.useWatchValue('shipsInternationally');
参考资料
对于超出基础表单的用例,编写代码前请阅读以下两份参考资料:
references/patterns.md— 适用于以下内容:同一表单用于不同记录(编辑对话框)、将焦点移至第一个无效字段、多个提交按钮、用户输入时更改值、嵌套对象、数组字段、列表中的列表和formRootRule、异步验证(规则和异步架构)、条件字段、条件验证、多步骤表单、从服务加载初始值、保存并设置新的基线、从组件外部控制表单、自定义输入、跨组件的表单上下文、transformValues、独立的useField、提交后的服务端错误references/api.md— 适用于其他所有内容。这里是唯一列出每个useForm选项和返回成员(watch、onValuesChange、enhanceGetInputProps、resetField、clearFieldError、touchTrigger等)的地方,还包括useField、createFormContext、createFormActions、schemaResolver、内置验证器和类型
查找资料
如果参考资料没有涵盖你需要的内容,请勿猜测:
- 如果已连接 Mantine MCP 服务(
@mantine/mcp-server),请使用search_docs和get_item_doc - 否则,请获取
https://mantine.dev/llms.txt并打开其中链接的表单页面