☰
5分钟上手Formisch:用Valibot模式在React中打造第一个类型安全登录表单
2026/10/15 18:03:28 网站建设 项目流程

【免费下载链接】formisch

The lightweight, schema-first, and fully type-safe form library for React, Solid, Vue, Svelte and more.

项目地址:https://gitcode.com/gh_mirrors/fo/formisch
点击查看免费下载

Formisch 是一款轻量级、Schema 优先、完全类型安全的 React 表单库。它基于 Valibot 做表单验证,把表单状态管理与校验规则合二为一,包体积仅约 2.5 kB 起步。本文带你用 5 分钟,在 React 中用 Valibot 模式打造第一个类型安全的登录表单——定义 Schema、连接输入框、处理提交,全程零手动类型声明,编辑器自动补全字段路径。

Formisch 表单库简介:轻量、快速、类型安全

在动手之前,先了解 Formisch 的核心优势,这也是它区别于传统 React 表单库的关键:

  • 小包体积:模块化设计,按需引入,起始约 2.5 kB
  • Schema 验证:基于 Valibot,一份 Schema 同时承担结构与验证规则
  • 端到端类型安全:字段路径、输入值、错误信息全链路类型推断,编辑器内自动补全
  • 细粒度更新:只更新必要的 DOM,避免整表单重渲染
  • 无头设计(Headless):不绑定任何 UI 组件,样式与组件库自由组合
  • 多框架支持:同一套心智模型覆盖 React、Vue、Svelte、Solid、Preact、Qwik、Angular 等

下图是 Formisch 官方文档中登录表单的示例代码,useForm、<Form />与<Field />三者组合就是整篇文章的主角:

一键安装步骤:安装 Formisch 与 Valibot 依赖

Formisch 使用 Valibot 作为验证引擎,Valibot 是它的 peer dependency,需要先装 Valibot,再装 Formisch。在终端执行:

# 1. 先安装 Valibot 验证库 npm install valibot # 2. 再安装 Formisch 的 React 包 npm install @formisch/react

💡Tip:如果使用 TypeScript,建议在tsconfig.json中开启strict模式(要求 TypeScript ≥ 5.0.2),这样 Schema 的类型推断才能完整生效。

安装完成后即可在任意文件中导入:

import { Form, Field, useForm } from '@formisch/react';

详细的安装说明可参考官方文档 installation/index.mdx/react/guides/(get-started)/installation/index.mdx)。

第一步:用 Valibot Schema 定义登录表单结构

Formisch 是schema-first(模式优先)的表单库:不写 TypeScript 类型,而是写 Valibot Schema,类型会由 Schema 自动推导出来。

一个登录表单通常只有两个字段:邮箱和密码。用v.object定义结构,用v.pipe串联校验规则,并附上清晰的错误提示:

import * as v from 'valibot'; const LoginSchema = v.object({ email: v.pipe( v.string(), v.nonEmpty('Please enter your email.'), v.email('The email address is badly formatted.') ), password: v.pipe( v.string(), v.nonEmpty('Please enter your password.'), v.minLength(8, 'Your password must have 8 characters or more.') ), });

Valibot Schema 类型推断:错误信息获得精确类型/react-form-library-comparison/type-safe-issues.jpg)

上图展示了 Valibot 的类型能力:连错误信息本身都会被推断为精确的联合类型(如v.StringIssue | v.MinLengthIssue<string, 1>),这就是 Formisch 类型安全的底层来源。

两个使用要点:

  1. 字段顺序即页面顺序:提交失败时 Formisch 会自动聚焦第一个出错的字段,所以 Schema 中的字段顺序请与页面布局保持一致。
  2. Schema 决定可提交的数据:可选项记得用v.optional(…)声明,表单只有在完全匹配 Schema 时才能提交。

更多 Schema 写法可查阅官方指南 define-your-form/index.mdx/react/guides/(main-concepts)/define-your-form/index.mdx)。

第二步:用 useForm 钩子初始化 React 表单

Schema 定义好后,用useForm钩子在组件中初始化表单实例。它会根据 Schema 创建表单状态仓库(form store),类型自动推断,无需任何手动声明:

import { Field, Form, useForm } from '@formisch/react'; export default function LoginPage() { const loginForm = useForm({ schema: LoginSchema, }); return ( <Form of={loginForm} onSubmit={(output) => console.log(output)}> {/* 表单字段写在这里 */} </Form> ); }

useForm接受以下常用配置项:

配置项说明
schema你的 Valibot Schema,表单的蓝图
initialInput字段初始值(可选)
emptyInput必填字段无初始值时的空值,默认为{ string: '' }
validate何时首次校验,默认'submit'
revalidate首次校验后何时重新校验,默认'input'

Formisch 会为每个字段同时追踪初始值与当前值:当两者不一致时isDirty变为true,这让"是否有未保存修改"这类判断变得非常自然。

该钩子的实现位于 useForm.ts,配置选项详见 create-your-form/index.mdx/react/guides/(main-concepts)/create-your-form/index.mdx)。

第三步:用 Form 和 Field 组件连接输入框

<Form />是原生<form>元素的薄封装,负责验证与提交;<Field />是无头组件,通过of(表单实例)和path(字段路径)连接到 Schema 中的某个字段,并在 children 函数中把字段状态交给你:

import { Field, Form, useForm } from '@formisch/react'; export default function LoginPage() { const loginForm = useForm({ schema: LoginSchema }); return ( <Form of={loginForm} onSubmit={(output) => console.log(output)}> <Field of={loginForm} path={['email']}> {(field) => ( <div> <input {...field.props} value={field.input} type="email" /> {field.errors && <div>{field.errors[0]}</div>} </div> )} </Field> <Field of={loginForm} path={['password']}> {(field) => ( <div> <input {...field.props} value={field.input} type="password" /> {field.errors && <div>{field.errors[0]}</div>} </div> )} </Field> <button type="submit">Login</button> </Form> ); }

字段状态对象(field store)包含这些常用属性:

  • field.input:当前输入值,类型由 Schema 推断
  • field.errors:当前错误信息数组,可直接渲染
  • field.props:展开到<input>上的事件处理器与属性(含name、ref,出错字段还会自动autoFocus)
  • field.isTouched/field.isEdited/field.isDirty/field.isValid:交互与脏值状态

如果你拆出独立的字段组件,可以改用useField钩子直接获取字段状态,实现位于 useField.ts;<Field />本质上是它的薄封装(Field.tsx)。

⚠️ 注意:field.props中的事件处理器从 DOM 读取的值是字符串。对v.number()、v.date()这类非字符串字段,需要受控写法(手动绑定value等属性)来保证类型正确。

第四步:处理表单提交与加载状态

最后一步:处理提交。给<Form />传入onSubmit函数,第一个参数就是通过验证的表单值——类型与 Schema 输出一一对应:

const submitForm: SubmitHandler<typeof LoginSchema> = async (values) => { const response = await fetch('/api/login', { method: 'POST', headers: { 'Content': 'application/json' }, body: JSON.stringify(values), // { email: string, password: string } }); if (response.ok) console.log('登录成功!'); };

提交期间还可以用loginForm.isSubmitting显示加载态:

<button type="submit" disabled={loginForm.isSubmitting}> {loginForm.isSubmitting ? 'Submitting...' : 'Login'} </button>

表单仓库还提供isSubmitted、isValidating、isTouched、isDirty、isValid等响应式状态。提交细节(含不包裹<Form />时用handleSubmit的场景)见 handle-submission/index.mdx/react/guides/(main-concepts)/handle-submission/index.mdx)。

常见问题与扩展学习路径

Q:为什么必须先安装 Valibot?A:Valibot 是 Formisch 的 peer dependency,负责 Schema 定义与验证执行,Formisch 核心只管理状态。

Q:嵌套字段怎么连接?A:path接受字符串数组,如path={['user', 'email']}对应v.object({ user: v.object({ email: v.string() }) }),嵌套路径同样是类型安全的。

Q:如何给复杂表单编程式控制字段?A:Formisch 提供一套方法 API,如setInput、reset、validate、getErrors、isDirty、submit等,按需导入即可。

想继续深入,推荐这几个仓库内的学习路径:

  • 官方文档:docs react 目录/react)
  • React Playground(含登录、嵌套、字段数组等完整示例):playgrounds/react/
  • 真实业务示例(Svelte 发票表单,含金额/数量转换与字段数组):schema.ts
  • React 框架包源码:frameworks/react/src/
  • 核心包(框架无关的状态管理):packages/core/src/

至此,你已经用 5 分钟跑通了 Formisch + Valibot 的核心工作流:Schema 定义 → useForm 初始化 → Field 连接 → onSubmit 提交。以后新增字段只需改 Schema,类型、验证、错误提示全部自动跟上——这正是 Schema 优先表单库的魅力所在 🚀

【免费下载链接】formisch

The lightweight, schema-first, and fully type-safe form library for React, Solid, Vue, Svelte and more.

项目地址:https://gitcode.com/gh_mirrors/fo/formisch
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询