Skip to content

Conversation

@Komoszek
Copy link

@Komoszek Komoszek commented Nov 20, 2025

Currently ReactElement can only be passed to message in the rules passed to the Field. This PR fixes types a bit, which in turn means that ReactElement can also be passed to warnings/errors/validation messages and getFieldError/getFieldsError/getFieldWarning have correct return types.

Summary by CodeRabbit

发布说明

  • 新功能

    • 表单验证的错误/警告消息现在支持 React 元素,可在验证提示中展示富文本、图标或链接,提升展示能力与用户体验。
  • 重构

    • 表单查询/验证相关的错误与警告接口已统一为更丰富的消息类型,相关 API 返回与事件会携带该富消息格式(可能影响依赖旧字符串数组的集成)。

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Nov 20, 2025

@Komoszek is attempting to deploy a commit to the React Component Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Nov 20, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

引入公开类型 Message = string | ReactElement,并将表单系统中所有错误/警告相关类型从 string[] 迁移为 Message[],同时同步更新 Field、useForm、interface 及示例代码的签名和内部验证/聚合路径。

Changes

内聚体 / 文件(s) 变更总结
类型系统新增
src/interface.ts
新增导出类型 `Message = string
字段实现与状态
src/Field.tsx
导入 Message 类型;EMPTY_ERRORS/EMPTY_WARNINGS 类型改为 never[];字段状态 errors/warningsstring[] -> Message[];验证 promise 类型从 Promise<string[]> -> Promise<RuleError[]>,本地 nextErrors/nextWarnings 改为 Message[]
表单存储 / API
src/useForm.ts
导入 MessagegetFieldError/getFieldWarning 返回类型由 string[] -> Message[];内部缓存、聚合与通知流程改为处理 Message[];验证结果与合并逻辑调整为基于新的错误类型。
示例与文档
docs/examples/validate-perf.tsx
更新导入以使用新的 Message 类型;示例中 onPasswordErrorerrors 参数由 string[] -> Message[]

Sequence Diagram(s)

sequenceDiagram
  participant App as 应用
  participant Form as FormStore
  participant Field as Field
  participant Rule as ValidatorRule

  rect rgb(230,245,255)
    Note over App,Form: 用户触发验证/提交
    App->>Form: validateFields()
    Form->>Field: validateRules()
    Field->>Rule: run validators
    Rule-->>Field: 返回 RuleError { errors: Message[] }
    Field-->>Form: resolve validatePromise with RuleError[]
  end

  rect rgb(235,255,230)
    Note over Form,Field: 汇总并通知
    Form->>Form: merge FieldError.errors (Message[])
    Form->>App: notify onFieldsChange / onFinish with Message[]
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 分钟

  • 需重点检查文件与接口间的类型一致性和向后兼容性,尤其是:
    • src/interface.ts 中 Message 类型及其在所有导出接口的正确应用
    • src/Field.tsx 中验证 promise 与 RuleError 的类型传播
    • src/useForm.ts 中缓存、聚合与通知逻辑在类型变更后的正确性
    • 与现有自定义验证器(仍返回 string)的兼容处理

Possibly related PRs

Suggested reviewers

  • zombieJ

走过一遍

该拉取请求引入了新的 Message 类型定义(string | ReactElement),并将整个表单验证系统中的错误和警告类型从 string[] 改为 Message[],包括字段元数据、验证规则、表单实例方法和内部验证流程。

诗歌

🐰 消息不再只是字符串,

也能是元素轻盈舞,
验证流中新语义,
错误花样更芳馨,
小白兔为改动欢欣~ 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰准确地概括了此次变更的主要目标:允许在错误/警告和验证消息中传递ReactElement类型。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e197dea and edb3477.

📒 Files selected for processing (1)
  • src/useForm.ts (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/useForm.ts (2)
src/interface.ts (3)
  • NamePath (7-7)
  • Message (12-12)
  • FieldError (129-133)
src/utils/valueUtil.ts (1)
  • getNamePath (15-17)
🔇 Additional comments (6)
src/useForm.ts (6)

19-19: 正确引入 Message 类型。

引入 Message 类型以支持错误和警告消息使用 string | ReactElement,与 interface.ts 中的类型定义保持一致。


386-392: 正确更新 getFieldError 返回类型。

返回类型从 string[] 更新为 Message[],与 FieldError 接口中的 errors 字段类型一致。


394-400: 正确更新 getFieldWarning 返回类型。

返回类型从 string[] 更新为 Message[],与 FieldError 接口中的 warnings 字段类型一致。


881-890: 正确更新错误缓存类型。

缓存类型从 NameMap<string[]> 更新为 NameMap<Message[]>,与 FieldError.errors 的类型保持一致,确保在 triggerOnFieldsChange 中正确存储和检索错误消息。


1025-1034: 正确更新 catch 块的类型注解(已解决之前的评审意见)。

参数类型从 { name: InternalNamePath; errors: string[] }[] 更新为 FieldError[],这与验证 Promise 链中拒绝值的实际结构一致(第 987-991 行),并且正确反映了 errorswarnings 字段现在是 Message[] 类型。

注意:此更改解决了之前评审中标记的类型不一致问题。


975-999: 类型更新已验证,确认无误。

验证结果显示,RuleError 接口中的 errors 字段确实已定义为 Message[] 类型(src/interface.ts 第 136 行)。这与 src/useForm.tsmergedErrorsmergedWarnings 的类型更新完全一致。

代码流程正确:

  • ruleErrors 数组迭代访问 errors 属性(类型为 Message[]
  • 将这些错误正确地推送到相应的 merged* 数组中
  • 最终在 FieldError 对象中使用这些类型一致的数组

无需进一步调整。


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @Komoszek, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the flexibility of message handling within the form validation system by allowing React elements to be used directly in error, warning, and general validation messages. This change involves a comprehensive update to the type definitions across the codebase, ensuring that the API correctly reflects this new capability and provides a more consistent developer experience.

Highlights

  • Enhanced Message Flexibility: The system now supports passing ReactElement directly to error, warning, and validation messages, expanding beyond the previous limitation of only rules.message.
  • Type System Alignment: Return types for getFieldError, getFieldsError, and getFieldWarning have been updated to correctly reflect the ability to return ReactElements, ensuring type safety and consistency across the API.
  • New Message Type Definition: A new Message type has been introduced, defined as string | ReactElement, to centralize and simplify type declarations for all message-related properties and methods.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request does a great job of enabling ReactElement for error and warning messages, which significantly improves the flexibility of displaying validation feedback. The introduction of the Message type alias and its consistent application across the codebase is well-executed. The type definitions have been updated thoroughly in src/interface.ts, and the component logic in src/Field.tsx and src/useForm.ts has been adjusted accordingly.

I've found one minor issue where a type annotation was missed during the refactoring, which I've pointed out in a specific comment. Addressing this will ensure full type safety and consistency.

Overall, this is a valuable enhancement to the library.

Comment on lines +975 to +976
const mergedErrors: Message[] = [];
const mergedWarnings: Message[] = [];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While updating these types to Message[] is correct, a related type annotation in this file was missed and should also be updated to prevent potential runtime errors and ensure type consistency.

In the catch block for returnPromise within the validateFields method (around line 1025), the errors property in the type for the results parameter is still string[]. It should be Message[].

Suggested Change:

In src/useForm.ts around line 1025, please update the type signature:

// before
.catch((results: { name: InternalNamePath; errors: string[] }[]) => {

// after
.catch((results: { name: InternalNamePath; errors: Message[] }[]) => {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed that by using FieldError

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/useForm.ts (1)

970-1001: 将外层 catch 的类型声明从 string[] 改为 Message[]

经验证,您的指出是正确的。类型链路中确实存在不一致:

  • 内层 catch 处理 (第974-998行):RuleError.errors 定义为 Message[],经过合并后的 mergedErrors 类型为 Message[],通过 Promise.reject() 传递出去
  • 外层 catch 处理 (第1025行):错误声明为 errors: string[],但实际接收的是 Message[]
  • ValidateErrorEntity (src/interface.ts:91):其 errorFields 字段定义为 { name: InternalNamePath; errors: Message[] }[],与外层声明的 string[] 不符

第1027行 errorList[0]?.errors?.[0] 实际会得到 Message(可为 ReactElement),不仅仅是字符串。第1031行将 errorList 作为 errorFields 传入时,类型标注的错误会隐藏运行时的潜在问题。

建议按原建议修改第1025行的类型注解:

-      .catch((results: { name: InternalNamePath; errors: string[] }[]) => {
+      .catch((results: { name: InternalNamePath; errors: Message[] }[]) => {

这样可以保证整个验证流程的类型一致性。

🧹 Nitpick comments (1)
src/interface.ts (1)

12-13: Message 类型引入与全局替换基本一致,但属于 TS 公共 API 的类型变更

优点与一致性:

  • 新增 Message = string | ReactElement 并在以下位置统一替换为 Message[]
    • Meta.errors/warnings
    • FieldError.errors/warnings
    • RuleError.errors
    • ValidateErrorEntity.errorFields[].errors
    • FieldEntity.getErrors/getWarnings 以及 FormInstance.getFieldError/getFieldWarning
  • ValidatorRule.messageBaseRule.messageValidateErrorEntity.message 改为 Message,再加上扩展后的 ValidateMessage = string | (() => string) | ReactElement,整体上把“错误值”和“配置化消息”清晰区分开了。
  • ValidateMessages 增加了 enum?: ValidateMessage,能匹配示例里对 enum 消息的配置。

需要注意的地方:

  • 由于 FormInstance.getFieldError/getFieldWarningValidateErrorEntity.errorFields 等对外暴露的类型从 string[] 变为 Message[],这对 TypeScript 使用者是一个显式的 breaking change(例如泛型约束里写死 string[] 的代码会编译失败)。建议在版本号与变更日志中明确标注这一点,方便下游升级。
  • 目前 Validator 回调仍然声明为 (error?: string) => void,这意味着如果用户希望在自定义 validator 中直接返回 ReactElement,需要绕过当前类型。考虑到本 PR 目标主要是让 message / validateMessages 支持 ReactElement,这点可以作为后续增强来评估。

总体来说,这个文件里对 Message 的引入和使用是一致且合理的,只需在发布时给下游明确升级预期即可。

Also applies to: 17-18, 57-69, 91-96, 98-137, 270-292, 319-366

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cbf2162 and e197dea.

📒 Files selected for processing (4)
  • docs/examples/validate-perf.tsx (2 hunks)
  • src/Field.tsx (5 hunks)
  • src/interface.ts (8 hunks)
  • src/useForm.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
docs/examples/validate-perf.tsx (1)
src/interface.ts (1)
  • Message (12-12)
src/useForm.ts (2)
src/interface.ts (2)
  • NamePath (7-7)
  • Message (12-12)
src/utils/valueUtil.ts (1)
  • getNamePath (15-17)
src/Field.tsx (1)
src/interface.ts (2)
  • RuleError (135-138)
  • Message (12-12)
🔇 Additional comments (3)
docs/examples/validate-perf.tsx (1)

7-7: 示例中 Message 引入与 onPasswordError 类型更新是合理的

这里将 MessageValidateMessages@/interface 引入,并把 onPasswordErrorerrors 参数更新为 Message[],与 Meta.errors 的新类型保持一致,示例代码能同时覆盖字符串和 ReactElement 错误信息,整体没有类型或运行时风险。

Also applies to: 37-39

src/useForm.ts (1)

19-20: 错误 / 警告返回值改为 Message[] 的实现是连贯的

  • Message 类型引入,并在 getFieldError / getFieldWarning 返回 Message[],与 FormInstanceFieldEntity.getErrors/getWarnings 的新签名一致。
  • triggerOnFieldsChangeNameMap<Message[]> 的缓存类型也与 FieldError 的更新保持同步,避免后续再出现 string[] / Message[] 混用问题。

这部分逻辑和类型衔接良好,看不到明显问题。

Also applies to: 364-400, 868-900

src/Field.tsx (1)

13-14: Field 内部改用 Message[] 与新的错误模型一致

  • 引入 Message,并将 errors / warnings 字段改为 Message[],与 RuleError.errors: Message[]Meta.errors/warnings: Message[] 的定义对齐。
  • EMPTY_ERRORS / EMPTY_WARNINGS 使用 never[] 作为共享空数组哨兵,在 TS 类型层面可以避免误修改,同时又能安全赋值给 Message[]RuleError[]
  • validatePromisevalidateRules 返回类型统一为 Promise<RuleError[]>validateOnly 分支也保持一致。
  • validateRules 中通过 warningOnly 拆分到 nextErrors / nextWarnings,最终写回 this.errors / this.warnings,可同时承载字符串和 ReactElement。

整体来看,Field 这一侧对新 Message 类型的接入是自洽的,没有发现明显类型或运行时问题。

Also applies to: 33-35, 141-147, 395-481, 503-523

@Komoszek
Copy link
Author

@zombieJ what do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant