
react-use 中的 useStateValidator为任意状态编写声明式校验逻辑【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use导读useStateValidator是 react-use 提供的一个状态校验 Hook其核心职责是每当被监听的状态发生变化时自动调用用户提供的 validator 函数并重新计算校验结果。它适合表单校验、输入合法性检测、跨字段联动校验等场景返回的校验结果以元组形式呈现并支持同步与异步两种校验模式。读完本文你将掌握useStateValidator的完整 API、同步/异步校验写法、底层实现原理以及如何用现有测试用例验证它的行为。一、Hook 定位状态驱动的校验器在 react-use 的 Hook 体系中useStateValidator 属于「State」类目下的状态派生工具与useStateList、useStateWithHistory等同属一类并在 src/index.ts 中作为默认导出对外暴露。它的核心设计思想非常朴素给定一个 state 和一个 validator 函数Hook 负责在 state 每次变化时自动重跑 validator并把返回值作为校验状态管理起来。文档 docs/useStateValidator.md 中的一句话概括了其全部行为契约Each time given state changes - validator function is invoked.每次给定状态变化时validator 函数即被调用。相比在组件里手写useEffectuseState去维护校验结果useStateValidator把这些样板逻辑统一收敛到 Hook 内部让业务代码只需关心「怎么校验」而无需关心「何时校验」。二、API 参考签名与返回值2.1 函数签名const [validity, revalidate] useStateValidator( state: any, validator: (state, setValidity?) [boolean | null, ...any[]], initialValidity: any );结合 src/useStateValidator.ts 的泛型定义完整签名如下function useStateValidatorV extends ValidityState, S( state: S, validator: StateValidatorV, S, initialState?: V ): UseStateValidatorReturnV其中核心类型定义为export type ValidityState [boolean | undefined, ...any[]] | [undefined]; export interface StateValidatorV, S { (state: S): V; (state: S, dispatch: DispatchSetStateActionV): void; } export type UseStateValidatorReturnV [V, () void];2.2 参数与返回值详解成员类型说明validity[boolean \| null, ...any[]]校验结果。首个元素是严格的可空布尔值true合法 /false非法 /null或undefined表示尚未计算或无法判定其余元素可携带任意附加数据如错误码、错误消息等revalidate() void手动触发一次校验的函数返回后不会改变 state 本身validator(state, setValidity?) [boolean \| null, ...any[]]校验函数。接收当前 state若声明了第二个参数setValidity则 Hook 不再自动写入校验结果改由你在合适时机手动调用setValidity提交结果——这正是异步校验的开关stateany被监听的状态源其引用变化会触发重新校验setValidity(value) void由 Hook 注入的校验结果写入器即 React 的setState仅当 validator 显式声明第二参数时才会被传入initialValidityany初始校验值默认[undefined]用于在首次校验尚未完成时占位注意文档示例中首元素类型写为boolean | null而源码类型定义中为boolean | undefined两者语义等价均表示「未知/未决」状态。官方 story 演示中即使用undefined表示未校验。三、基础用法同步校验一个数字输入文档 docs/useStateValidator.md 给出的完整示例实现了一个「仅当输入为偶数时合法」的数字输入框import * as React from react; import { useCallback } from react; import { useStateValidator } from react-use; const DemoStateValidator s [s ? null : (s * 1) % 2 0]; const Demo () { const [state, setState] React.useStatestring | number(0); const [[isValid]] useStateValidator(state, DemoStateValidator); return ( div divBelow field is valid only if number is even/div input typenumber min0 max10 value{state} onChange{(ev: React.ChangeEventHTMLInputElement) { setState(ev.target.value); }} / {isValid ! null span{isValid ? Valid! : Invalid}/span} /div ); };几个值得注意的细节解构写法const [[isValid]] useStateValidator(...)先取出元组第一个元素validity它本身也是数组再取其中的首元素isValid空值语义validator 在s 时返回null表示「未判定」UI 上通过isValid ! null来隐藏未判定状态下的提示文本每次输入变化自动校验只要setState导致state引用变化useStateValidator内部的useEffect就会自动重新调用 validator无需手工触发。配套的可运行版本见 stories/useStateValidator.story.tsx其 validator 使用undefined作为空值标记s ? undefined : (s * 1) % 2 0行为与文档示例一致。四、深入源码Hook 内部如何工作阅读 src/useStateValidator.ts 全文仅 39 行可以清晰看到它由四个关键部件构成4.1 用 ref 缓存最新的 state 与 validatorconst validatorInner useRef(validator); const stateInner useRef(state); validatorInner.current validator; stateInner.current state;每次渲染时都会把最新的validator和state写入 ref。这样做的目的是让内部缓存的validate回调通过useCallback记忆化永远能读到最新值同时避免因 validator 函数引用变化而重复重建回调。4.2 内部校验状态const [validity, setValidity] useState(initialState as V);校验结果存放于组件自身的useState中初始值来自第三个参数initialValidity默认[undefined]。4.3 validate 回调按参数个数分流同步/异步模式const validate useCallback(() { if (validatorInner.current.length 2) { validatorInner.current(stateInner.current, setValidity as DispatchSetStateActionV); } else { setValidity(validatorInner.current(stateInner.current)); } }, [setValidity]);这是整个 Hook 最精妙的分派逻辑通过检查 validator 函数的length声明的形参数决定走哪条路径。若 validator 只声明一个参数(state)属于同步校验Hook 直接调用它拿到返回值并setValidity写入若 validator 声明了两个参数(state, setValidity)属于异步校验Hook 把setValidity注入给 validator由 validator 自行在异步回调网络请求、setTimeout、Promise 等完成后提交结果Hook 不再自动写入。这一设计让同一份 Hook 实现同时兼容「同步返回结果」和「回调式异步结果」两种模式且完全不需要额外的配置项。4.4 状态变化时自动触发useEffect(() { validate(); }, [state]);useEffect以state为依赖首次挂载执行一次之后每次state引用变化再执行一次。这正是文档所述「Each time given state changes - validator function is invoked」的代码来源。五、异步校验借助 setValidity 手动提交结果当校验逻辑涉及异步操作如调用后端 API、等待用户防抖输入、读取文件等时只需让 validator 声明第二个参数setValidityimport { useStateValidator } from react-use; const validateAsync (state, setValidity) { // 先置为“校验中”状态 setValidity([undefined]); // 模拟异步校验1 秒后得出结果 setTimeout(() { setValidity([state.length 3]); }, 1000); }; const Demo () { const [state, setState] React.useState(); const [[isValid]] useStateValidator(state, validateAsync); return ( div input value{state} onChange{(e) setState(e.target.value)} / {isValid undefined ? 校验中... : isValid ? 合法 : 非法} /div ); };要点说明只要 validator 声明了第二个形参Hook 就不会自动写入结果避免异步返回前被同步返回值覆盖异步期间可主动setValidity([undefined])占位配合 UI 展示「校验中」状态每个 state 变化都会重新触发一次异步校验若需防抖可与useDebounce等 Hook 组合使用注意依赖的 state 引用必须变化才会触发。六、测试验证行为契约的完整佐证仓库中 tests/useStateValidator.test.ts 用testing-library/react-hooks完整锁定了该 Hook 的行为契约可作为你理解其语义的权威参照测试用例验证的行为should return an array of two elements返回值是一个二元数组[校验结果, revalidate函数]且首次校验结果为[true]first element should represent current validity statestate 从 1 → 3均为奇数时validity保持[true]变为 4偶数后变为[false]证明校验结果随 state 同步更新second element should re-call validation手动调用revalidate()后validator 被调用的次数 1validator have to be called on init plus on each state update挂载时调用 1 次此后每次setState再调用 1 次3 次 state 更新对应 3 次调用should pass to validator one parameter - current state同步模式下validator 每次仅收到一个参数且参数值等于当前 stateif validator expects 2nd parameter it should pass a validity setter there当 validator 声明两个形参时第二个参数是函数即setValidity且 Hook 不再自动写入结果改由 validator 内部调用 setter 提交其中最后一个用例与源码validatorInner.current.length 2的分派逻辑一一对应是理解「异步模式」语义的最直接证据。七、类型层面泛型约束与提示从源码导出类型可以看到ValidityState被约束为[boolean | undefined, ...any[]] | [undefined]即首元素必须是boolean | undefined之后可以追加任意数量的附加数据...any[]也允许只有undefined的退化形态用于初始占位。在使用 TypeScript 时建议为 validator 显式标注返回类型例如import { useStateValidator, ValidityState } from react-use; const validator (s: string): ValidityState [ s.length 6, s.length 6 ? 密码长度至少 6 位 : null, // 附加的错误提示数据 ];这样validity的首元素与附加数据都能获得类型推断方便在 UI 中消费错误消息等附加信息。八、小结与适用场景useStateValidator把「状态变化 → 触发校验 → 更新校验结果」这条链路封装成一个极简 Hook主要优势可归纳为声明式只需提供state与validator自动在 state 变化时重算同步/异步双模式通过 validator 形参数自动分流无需额外配置结果可扩展校验结果数组除首元素布尔值外可携带任意附加数据可手动重算revalidate可在不改变 state 的情况下强制重新校验。适合用于表单字段合法性校验、输入长度/格式检测、跨字段约束判断、异步唯一性检查等场景。若需要更完整的表单状态管理能力可将其与useSetState、useDebounce等 react-use Hook 组合使用。【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考