- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
本篇技术指南聚焦 docs/pages/components/form-formik/fragments/validation.md 所演示的 Formik 校验集成方案,讲解如何在 React Suite 表单体系中用useFormik的validate函数完成字段级校验,并通过Form.Group、Form.ErrorMessage组件把错误信息以气泡形式展示在输入框下方。读完本文,你将掌握 Formik 与 React Suite 组合校验的完整写法、错误消息组件的控制原理,以及如何把校验结果接入 React Suite 的Form提交链路。
一、为什么把校验交给 Formik
React Suite 自带基于 schema-typed 中的model属性)。但在 Formik 集成场景下,文档采用的方式是让 Formik 全权管理表单状态与校验逻辑,React Suite 只负责渲染控件和展示错误信息。这样做的直接好处:
- 校验逻辑与 UI 解耦,
useFormik的validate函数返回一个errors对象,字段名与错误文案一一对应; - 所有 React Suite 数据输入组件(
Input、DatePicker、Rate等)都可以共用同一套 Formik 状态,无需逐个适配; - 后续可以无缝切换到 Yup 或 Zod 等模式校验方案(见 yup-schema-validation.md),
errors的数据结构保持不变。
该集成文档位于 Formik 集成指南(en-US/index.md)的 "Validation" 小节,属于该指南中承上启下的核心示例。
二、手写 validate 的完整代码
validation.md给出的是一个可直接运行的完整示例,核心思路分三步:定义useFormik配置 → 封装带错误展示的Field组件 → 用Form承接提交。完整代码如下:
import { useFormik } from 'formik'; import { Input, Button, Form } from 'rsuite'; const Field = ({ error, ...rest }) => { return ( <Form.Group> <Input {...rest} /> <Form.ErrorMessage show={!!error} placement="bottomStart"> {error} </Form.ErrorMessage> </Form.Group> ); }; const App = () => { const formik = useFormik({ initialValues: { name: '', email: '' }, validate: values => { const errors = {}; if (!values.name) { errors.name = 'Required'; } if (!values.email) { errors.email = 'Required'; } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) { errors.email = 'Invalid email address'; } return errors; }, onSubmit: values => { alert(JSON.stringify(values, null, 2)); } }); return ( <Form onSubmit={formik.handleSubmit}> <Form.Stack fluid> <Field name="name" placeholder="Name" value={formik.values.name} error={formik.errors.name} onChange={value => formik.setFieldValue('name', value)} /> <Field name="email" placeholder="Email" value={formik.values.email} error={formik.errors.email} onChange={value => formik.setFieldValue('email', value)} /> <Button appearance="primary" type="submit"> Submit </Button> </Form.Stack> </Form> ); }; ReactDOM.render(<App />, document.getElementById('root'));2.1 validate 函数的返回契约
validate接收当前全部字段值values,返回一个errors对象:
- 字段名即 key:
errors.name、errors.email与formik.values中的字段一一对应; - 值为空对象表示校验通过:示例中
const errors = {}作为兜底返回; - 值为错误文案字符串:例如
'Required'、'Invalid email address',它们会被直接渲染进Form.ErrorMessage。
示例中的邮箱校验使用了经典的正则/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,注意末尾的i标志使大小写不敏感,因此[A-Z]与[a-z]均可匹配。该写法验证了两个关键行为:
- 空值优先拦截:
email为空时只报'Required',不会继续执行正则产生重复错误; - 校验短路:
else if保证只有非空邮箱才走格式校验。
2.2 Field 组件的封装模式
示例把「输入控件 + 错误提示」封装成一个私有组件Field,通过解构把error从其余 props 中剥离:
Form.Group提供字段的纵向布局容器;<Input {...rest} />将name、placeholder、value、onChange等 props 透传给输入控件;<Form.ErrorMessage show={!!error} placement="bottomStart">{error}</Form.ErrorMessage>仅在error有值时渲染气泡错误提示,bottomStart表示提示出现在控件左下侧。
Form.ErrorMessage在 React Suite 源码中的行为与此完全吻合:查看 FormErrorMessage.tsx 可确认,它通过show属性控制显隐——show为真时才渲染气泡结构,否则返回null;placement通过data-placement属性下发到 DOM,配合样式实现定位。这正是!!error布尔转换之所以必要的底层原因。
需要特别说明的是,这里的Form.ErrorMessage是完全受控的:它不读取 React Suite 内部表单上下文,错误文案完全由 Formik 的formik.errors提供。这与 React Suite 原生<Form>的errorFromContext机制(见 Form.tsx)相互独立、互不干扰,因此可以在不启用model校验的情况下单独工作。
三、提交链路:Formik 的 handleSubmit 如何与 Form 配合
示例使用<Form onSubmit={formik.handleSubmit}>,注意这里引入的是 React Suite 的Form组件(而非原生<form>),但它只承担两个职责:
- 样式与布局:
Form.Stack fluid让内部字段在垂直方向排列并占满容器宽度; - 标准表单事件透传:React Suite
Form底层渲染为原生<form>元素(见 Form.tsx),并把onSubmit作为原生事件属性透传下去。
因此点击type="submit"的按钮时,原生submit事件触发formik.handleSubmit,Formik 会先执行validate,全部通过后才调用onSubmit回调并以alert展示格式化后的 JSON。若校验失败,onSubmit不会被调用,错误气泡即时更新——这是 Formik 默认的「提交时校验 + 变更后自动重新校验」行为。
对照基础示例(basic.md)可以看到,未接入校验时useFormik只配置initialValues和onSubmit,字段值通过formik.values读取、formik.setFieldValue写入;validation.md在此基础上仅新增validate与错误展示,状态管理方式完全一致,改动成本极低。
四、从手写 validate 到 Yup 模式校验
validation.md是校验链条的第一环,同指南中 yup-schema-validation.md 展示了它的升级形态:把validate函数替换为validationSchema属性,其余代码(Field封装、Form.Stack、错误气泡)完全复用:
const validationSchema = Yup.object().shape({ name: Yup.string().required('Required'), email: Yup.string().email('Invalid email address').required('Required') }); const formik = useFormik({ initialValues: { name: '', email: '' }, validationSchema, onSubmit: values => { alert(JSON.stringify(values, null, 2)); } });两种方式的对接点完全一致:无论错误来自手写validate还是 Yup,最终都收敛为{ fieldName: message }结构,因此Field组件无需任何改动。如果偏好 Zod,指南也提示可使用社区适配器zod-formik-adapter。React Suite 官方文档页面本身也声明了这两个集成依赖:formik@^2.4.5与yup@^1.3.3(见 index.tsx),可作为版本参考。
五、扩展:让所有数据输入组件复用同一套校验
Field封装还可以通过as属性泛化,从而让DatePicker、Rate等非输入型组件也接入 Formik 校验(见 other-input-components.md):
const Field = ({ error, as: Component = Input, ...rest }) => { return ( <Form.Group> <Component {...rest} /> <Form.ErrorMessage show={!!error} placement="bottomStart"> {error} </Form.ErrorMessage> </Form.Group> ); }; <Field as={DatePicker} name="date" value={formik.values.date} error={formik.errors.date} onChange={value => formik.setFieldValue('date', value)} />其校验模式与validation.md一脉相承,只是把 Yup 的校验规则换成Yup.date()、Yup.number().min(2).max(5)等。这说明只要遵循「value由formik.values驱动、onChange走setFieldValue、error交给Form.ErrorMessage」三条约定,React Suite 的任意数据输入组件都可以即插即用。
六、小结与落地方案
以validation.md为核心,一套可复用的 React Suite + Formik 校验方案可以总结为:
| 关注点 | 推荐做法 | 依据 |
|---|---|---|
| 状态与校验 | useFormik统一管理,validate返回errors对象 | validation.md |
| 错误展示 | Form.Group+Form.ErrorMessage show={!!error} | FormErrorMessage.tsx |
| 提交处理 | <Form onSubmit={formik.handleSubmit}>,透传原生事件 | Form.tsx |
| 升级路径 | 将validate替换为validationSchema(Yup),组件零改动 | yup-schema-validation.md |
| 组件扩展 | Field支持as属性,适配 DatePicker、Rate 等 | other-input-components.md |
按照这套方案,你可以在保持 React Suite 统一视觉与交互的前提下,获得 Formik 完整的校验与提交控制能力;后续无论切换 Yup、Zod 还是升级校验规则,Field组件与提交链路都无需结构性改动。
- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
相关推荐
Guzzle 7 PHP HTTP 客户端详解:以 mailcow-dockerized 中的实际集成应用为例
Guzzle 7 PHP HTTP 客户端详解:以 mailcow dockerized 中的实际集成应用为例 本篇技术指南以 mailcow dockeriz
前端UI组件txtai Summary 管道:使用抽象式文本摘要管道(text2text 模型)实现长文本自动摘要
txtai Summary 管道:使用抽象式文本摘要管道(text2text 模型)实现长文本自动摘要 导读 本文围绕 txtai 的 Summary(文本摘要
前端UI组件如何在3分钟内上手vscan?超简单安装与基础使用教程
如何在3分钟内上手vscan?超简单安装与基础使用教程 vscan是一款开源、轻量、快速、跨平台的网站漏洞扫描工具,能够帮助您快速检测网站安全隐患,功能涵盖端口
网络安全漏洞扫描应用安全渗透测试
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考