mcpField
M
mantine-form

mantine-form

github.com/mantinedev开发642.7k 次安装3 周前更新
代码仓库

关于 mantine-form

面向 Mantine 9.x 的技能,介绍如何使用 `@mantine/form` 构建表单,涵盖输入绑定、验证策略、受控与非受控模式,以及复杂表单行为。

主要功能

  1. 01非受控与受控表单模式
  2. 02输入属性与字段绑定
  3. 03规则、模式和函数验证
  4. 04提交、变更或失焦时验证
  5. 05值监听与重新渲染行为

适用场景

  1. 01使用 Mantine 输入组件构建表单
  2. 02通过模式验证字段
  3. 03减少输入时的重新渲染
  4. 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'(默认)
值的存储位置RefReact 状态
form.values不会更新,请使用 form.getValues()每次变化时更新
值变化时重新渲染否是
输入属性defaultValue + onChangevalue + 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 并打开其中链接的表单页面

评论

支持 Markdown