-
Notifications
You must be signed in to change notification settings - Fork 280
feat(form): usewatch #2882
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(form): usewatch #2882
Conversation
概述演练这个拉取请求引入了 NutUI React 表单组件的新功能,主要添加了 变更
序列图sequenceDiagram
participant User
participant Form
participant UseWatch
participant FormStore
User->>Form: 创建表单
Form->>FormStore: 初始化
User->>Form: 注册监听器
Form->>UseWatch: 绑定监听回调
User->>Form: 修改表单字段
Form->>FormStore: 更新数据
FormStore->>UseWatch: 触发回调
UseWatch->>User: 通知字段变化
可能相关的 PR
建议标签
建议审阅者
诗歌
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (19)
src/packages/form/types.ts (1)
34-35
: 合并了扩展属性 _init 到 InternalFormInstance。
使得内部表单实例在类型层面更完整,建议在对应逻辑中做好 _init 标记的说明或注释,便于后续维护。src/packages/form/useWatch.ts (2)
13-19
: stringify 函数的异常处理方式
此处在 JSON.stringify 出错时返回随机数,能避免崩溃,但可能导致数据追踪定位不便。可考虑更具体的处理方式。
42-44
: 建议使用可选链 (optional chaining)
此处通过短路运算判断 formInstance 与其 _init 属性,可改写为可选链,简化表达:- const isValidForm = formInstance && formInstance._init + const isValidForm = formInstance?._init🧰 Tools
🪛 Biome (1.9.4)
[error] 43-43: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/form/useWatch.taro.ts (2)
13-19
: stringify 函数的异常处理方式
与 H5 版本一致,若 JSON.stringify 出错即返回随机数。可根据业务需要,考虑打印错误日志或返回更具可读性的替代方案。
42-44
: 可选链用法建议
同 H5 版本建议,使用可选链可使逻辑更简洁,提高可维护性:- const isValidForm = formInstance && formInstance._init + const isValidForm = formInstance?._init🧰 Tools
🪛 Biome (1.9.4)
[error] 43-43: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/form/demos/h5/demo8.tsx (5)
15-17
: 错误提示反馈方式合理
提交失败时使用 Toast 展示错误信息,操作简单直接。也可以后续结合日志系统,记录详细错误信息便于排查。
23-25
: 确保 form 在组件卸载时正常清理
在使用 Form.useForm 创建表单实例时,最好在组件卸载阶段(或合适时机)清理不需要的资源。如果后续增加一些副作用逻辑,可考虑为 form 增加卸载逻辑。
24-32
: useWatch 监听实现
通过使用 Form.useWatch 直接监听指定字段的变化,能够实时获取最新值,简化了监听流程。但要注意当监听字段较多时,可评估性能,确保不会造成不必要的重新渲染。
50-79
: Picker 触发逻辑完善
Picker 组件通过 ref.open() 控制弹出时机,逻辑直观简单。但若后续需要多种触发方式或扩展逻辑,建议将 Picker 打开/关闭动作封装为可复用的方法,以保持统一管理。
36-40
: 提交回调处理
onFinish 与 onFinishFailed 参数命名准确,但建议后续将所有错误都统一处理或转换为用户可读文案,避免仅显示 JSON 内容。src/packages/form/demos/taro/demo8.tsx (4)
16-18
: 出错提示处理
使用 Taro.showToast 输出错误信息,保证了跨端体验一致。可考虑在错误信息过长时做截断或简化,以防弹窗显示不全。
20-22
: 提交成功提示
Taro.showToast 展示 JSON 字符串便于调试,但在实际产品中,可能需要更易读的文案。
24-33
: useWatch 监听值
结合 Form.useWatch 监听 username、picker、gender,能及时更新 UI。需注意目标组件避免过度渲染,特别是在性能敏感的场景,可以利用分段监听或自定义回调等方式优化。
50-80
: Picker 组件的使用
pickerOptions 在 Taro 环境下使用与 H5 一致,说明跨平台兼容性较好。后续如需动态更新选项,可考虑用状态管理统一维护,避免数据分散。src/packages/form/useform.taro.ts (1)
278-278
: _init 语义
在 getForm 返回对象里添加 _init 用于标识表单初始化状态,有助于区分不同生命周期,如有需要可以结合一些“是否完成初始化”的逻辑进一步完善流程。src/packages/form/useform.ts (4)
82-82
: 立即通知机制
updateStore 完成后立刻调用 notifyWatch,可以确保监听回调总是拿到最新的表单状态,合适且高效。若后续有批量更新或大规模表单场景,或可考虑批量触发策略。
229-235
: registerWatch 设计
registerWatch 将回调函数统一添加到 watchList 并能撤销,符合常见观察者模式,实现清晰简洁。后续若有分组或字段级别的监听需求,可考虑在注册时传入特定 namePath。
237-246
: notifyWatch 回调
遍历 watchList 并传入最新表单值与变动字段 namePath,功能完善。若项目复杂度提高,可考虑对比旧值与新值,或者只通知受影响字段的回调函数以减少不必要的刷新。
278-278
: getForm 中的 _init 标记
在返回的 form 对象中增加 _init 标记便于判断当前实例是否已经初始化,在初始化相关的流程中可以利用此字段进行容错或延迟渲染。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
package.json
(1 hunks)src/packages/form/demo.taro.tsx
(4 hunks)src/packages/form/demo.tsx
(4 hunks)src/packages/form/demos/h5/demo8.tsx
(1 hunks)src/packages/form/demos/taro/demo8.tsx
(1 hunks)src/packages/form/doc.md
(1 hunks)src/packages/form/index.taro.ts
(2 hunks)src/packages/form/index.ts
(2 hunks)src/packages/form/types.ts
(2 hunks)src/packages/form/useWatch.taro.ts
(1 hunks)src/packages/form/useWatch.ts
(1 hunks)src/packages/form/useform.taro.ts
(6 hunks)src/packages/form/useform.ts
(6 hunks)src/packages/form/utils.ts
(1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/packages/form/useWatch.taro.ts
[error] 43-43: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/form/useWatch.ts
[error] 43-43: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (30)
src/packages/form/utils.ts (2)
1-2
: 导入类型定义的使用正确且简洁。
该文件中对 InternalNamePath 和 NamePath 的导入符合实际需要,没有多余依赖。
3-9
: 函数实现逻辑清晰且涵盖null与undefined情况。
getNamePath 函数很好地保证了返回值一定是数组,增强了类型处理的安全性和兼容性,建议继续保持此模式。
src/packages/form/index.ts (3)
6-6
: 成功将 useWatch 整合到当前文件中。
import 声明简单明了,没有产生额外副作用。
21-21
: 为 CompoundedComponent 新增 useWatch 属性。
在类型层面提供了对 useWatch 的声明,能让外部在使用时获得更好的代码提示和约束。
28-28
: 将 useWatch 赋值到 InnerForm 的静态属性。
通过在组件上暴露 useWatch,可以更方便地在业务中配合其他 Form 能力使用。该做法简洁明了,无安全或可维护性问题。
src/packages/form/index.taro.ts (3)
6-6
: 成功将 Taro 版本的 useWatch 功能引入。
与本地文件关联合理,确保在小程序端也能使用同样的接口。
21-21
: 在 CompoundedComponent 类型中增加 useWatch 声明。
保持与 index.ts 一致,确保 Taro 版本的 Form 具有相同的静态能力。
28-28
: 将 useWatch 绑定到 InnerForm 组件。
统一对外暴露 useWatch,便于在多端共享相同的使用方式,避免逻辑分散。
src/packages/form/types.ts (2)
11-11
: 定义 InternalNamePath 类型,提升类型语义。
使用 (string | number)[] 表达路径数组,能保证后续在操作复杂表单路径时有更精准的类型约束。
36-42
: 添加 WatchCallback、WatchOptions 等类型以支持监听功能。
新增的回调类型和 WatchOptions 接口结构明确,为后续的 useWatch 等功能奠定了良好的类型基础。
src/packages/form/demo.tsx (5)
10-10
: 导入 Demo8 以展示新功能示例
本行引入 Demo8 组件,可满足 Form.useWatch 的展示需求。目前无明显问题。
21-21
: 新增中文文案:Form.useWatch 对表单数据监听
此项文本与功能相符合,方便用户在中文环境中了解监听表单数据的用法。
31-31
: 新增英文文案:Watch field data change with Form.useWatch
此处与中英文文案保持一致,可提升国际化体验。
53-53
: 展示标题区域:{translated.title6}
引入了标题6,对应 Form.useWatch 的演示部分。整体实现无安全或性能风险。
54-54
: 渲染 Demo8 组件
在此处实际渲染 Demo8,逻辑简单清晰,易于维护。
src/packages/form/demo.taro.tsx (5)
12-12
: 导入 Demo8 组件 (Taro 版本)
此导入与 H5 版本做法一致,用来在 Taro 环境下展示 Form.useWatch 的用法。
23-23
: 新增中文文案:Form.useWatch 对表单数据监听
此处增强了 Taro 端与 H5 端文案一致性,便于中文用户理解。
33-33
: 新增英文文案:Watch field data change with Form.useWatch
确保多语言环境下功能文案的准确性。
56-56
: 标题渲染:{translated.title6}
此行增加对 title6 的展示,提示用户对应功能演示位置。
57-57
: 渲染 Demo8 组件 (Taro 版本)
该示例在 Taro 端演示监听表单数据的功能,与 H5 端操作统一。
src/packages/form/useWatch.ts (2)
21-25
: isFormInstance 实用性检查
检查内部属性 _init,用于判断 form 是否有效。目前实现较直接,可适度补充注释阐明此判断逻辑。
27-85
: useWatch 主体逻辑
此函数在首次挂载时读取初始值,并通过 registerWatch 实现对表单值变化的监听。整体思路清晰,暂未发现明显危害性能或功能的问题,适合当前需求。
🧰 Tools
🪛 Biome (1.9.4)
[error] 43-43: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/form/useWatch.taro.ts (2)
21-25
: isFormInstance 函数实现
通过检查 _init 判断是否为表单实例,与其他文件用法一致。可在后续丰富此判断机制。
27-85
: useWatch 主体逻辑
函数结构合理,通过对表单值变动进行比较后更新组件状态,实现对任何指定字段或函数依赖的监测。当前实现可满足大多数监听需求。
🧰 Tools
🪛 Biome (1.9.4)
[error] 43-43: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
src/packages/form/demos/h5/demo8.tsx (1)
5-14
: 使用常量存储城市信息的做法值得肯定
将城市数据用常量数组存储,减少了代码冗余,也方便后续维护或扩展。
src/packages/form/useform.taro.ts (3)
70-70
: 深拷贝存储
在 getFieldsValue 时对 store 做 JSON 深拷贝,保证返回数据不会被意外修改,降低风险。
229-235
: registerWatch & cancelWatch
registerWatch 返回取消订阅函数,保证观察者模式的完整实现,使组件在必要时可以清理监听。此设计合理。
82-82
: updateStore 后的通知机制
在 store 更新后立即调用 notifyWatch 确保所有监听者能及时获得最新数据,但需要注意 watchList 过多带来的性能开销,可以在必要时进行节流或去抖。
src/packages/form/useform.ts (1)
69-70
: getFieldsValue 参数可选性
让 nameList 参数为可选,并支持 boolean,保证调用方灵活性。此处深拷贝也很好地避免外部对 store 的意外修改。
package.json (1)
108-109
: 请确认 rc-util 的版本兼容性
新增的 rc-util 依赖用于支持 useWatch 功能。建议:
- 验证与现有 React 版本的兼容性
- 确认该版本是否存在已知的安全漏洞
✅ Verification successful
Let me verify React compatibility by checking the package.json and rc-util's peer dependencies.
Let me check if React is listed in devDependencies and also look for any usage of rc-util in the codebase.
rc-util 依赖版本兼容性验证完成
经验证:
- rc-util 5.32.2 版本完全兼容项目使用的 React 18
- 当前最新版本为 5.44.2,所选版本相对较旧但仍在维护
- 未发现任何已知安全漏洞
- 仅在表单 useWatch 功能中使用了其 get 工具函数
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查 rc-util 的版本兼容性和安全问题
# 检查最新版本
curl -s https://registry.npmjs.org/rc-util/latest | jq '.version'
# 检查安全漏洞
gh api graphql -f query='
{
securityVulnerabilities(first: 5, ecosystem: NPM, package: "rc-util") {
nodes {
advisory {
summary
severity
publishedAt
}
vulnerableVersionRange
firstPatchedVersion {
identifier
}
}
}
}'
Length of output: 415
Script:
#!/bin/bash
# Check React version in package.json
cat package.json | jq '.dependencies.react, .dependencies["react-dom"]'
# Check rc-util's peer dependencies
curl -s https://registry.npmjs.org/rc-util/5.32.2 | jq '.peerDependencies'
Length of output: 211
Script:
#!/bin/bash
# Check React version in devDependencies
cat package.json | jq '.devDependencies.react, .devDependencies["react-dom"]'
# Check rc-util usage
rg "from 'rc-util" -A 2
Length of output: 466
private notifyWatch = (namePath: InternalNamePath[] = []) => { | ||
// No need to cost perf when nothing need to watch | ||
if (this.watchList.length) { | ||
const allValues = this.getFieldsValue(true) | ||
|
||
this.watchList.forEach((callback) => { | ||
callback(allValues, namePath) | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
notifyWatch 性能考虑
当前实现一次性通知所有 watchList 监听函数,如果 watchList 数量随业务扩张而增多,建议考虑分级通知或针对特定字段变化分别通知,以减少不必要的回调触发。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
registerWatch中会push watchList。调用useWatch后会添加一个watchList监听特定字段。 notifyWatch只会通知在useWatch中注册过监听函数的字段,已经针对特定字段分别触发了
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Niubility-SunLight 感谢补充说明,了解你在 useWatch
中基于特定字段来注册并触发监听逻辑。如果目前的实现已经能够有效区分字段并只触发必要的 watchList
回调,那性能上确实已做了不错的保障。后续如果 watchList
变得非常庞大或应用场景更复杂,需要更多精细化的性能优化时,再视情况评估即可。如有更多需要,欢迎随时讨论。
src/packages/form/doc.md
Outdated
### Hook | ||
|
||
Form.useForm() 创建 Form 实例,用于管理所有数据状态。 | ||
|
||
Form.useWatch() 用于直接获取 form 中字段对应的值。 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
建议补充 Hook 部分的详细说明
Hook 部分的文档需要增加以下内容:
- useWatch 的具体使用示例
- useWatch 的参数类型说明
- useWatch 的返回值类型说明
- useWatch 的常见使用场景
建议按照以下格式补充文档:
### Hook
Form.useForm() 创建 Form 实例,用于管理所有数据状态。
-Form.useWatch() 用于直接获取 form 中字段对应的值。
+Form.useWatch(name: NamePath) 用于监听字段值的变化。
+
+#### 参数
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| name | 字段名称 | `string \| number \| (string \| number)[]` | - |
+
+#### 返回值
+| 类型 | 说明 |
+| --- | --- |
+| any | 对应字段当前的值 |
+
+#### 示例
+```tsx
+const Demo = () => {
+ const [form] = Form.useForm();
+ const value = Form.useWatch('field', form);
+
+ return (
+ <Form form={form}>
+ <Form.Item name="field">
+ <Input />
+ </Form.Item>
+ <div>当前值: {value}</div>
+ </Form>
+ );
+};
+```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
文档已更新
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Niubility-SunLight 感谢你的更新,文档部分的改动已收到,辛苦了!如果后续还需要进一步补充或有其他问题,欢迎随时留言。
If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!
@Alex-huxiyang I'll review the changes in this PR. ✅ Actions performedReview triggered.
|
🤔 这个变动的性质是?
🔗 相关 Issue
💡 需求背景和解决方案
☑️ 请求合并前的自查清单
Summary by CodeRabbit
新特性
Demo8
,提供城市选择和表单数据监控功能。useWatch
钩子,允许用户实时监控表单字段的变化。Form.useWatch()
的说明。修复
package.json
的语法格式,确保依赖项正确列出。