-
-
Notifications
You must be signed in to change notification settings - Fork 272
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(useWatch): notify watch in preserve mode #577
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Codecov Report
@@ Coverage Diff @@
## master #577 +/- ##
=======================================
Coverage 99.82% 99.82%
=======================================
Files 16 16
Lines 1143 1148 +5
Branches 256 260 +4
=======================================
+ Hits 1141 1146 +5
Misses 2 2
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
这会有点怪异,什么情况下被依赖的项不见了,同时依赖项还要更新的?能举个例子么? |
例如表单有两个 step,不同 step 渲染的 fields 不同,但 step 1 的某字段值改变后会影响到 step 2 的一些字段的值。 此外还有一个场景,就是根据数组来渲染 fields,例如这个场景: React.useEffect(() => {
form.setFieldsValue({
items: [
{ name: 'a' },
{ name: 'b' },
],
});
}, []);
const items = Form.useWatch('items', form) || [];
return items.map((item, index) => (
<Field name={['items', index]} key={`${items}-${index}`}>
...
</Field>
)); 在一开始并没有 Field 被渲染,因此即使点击了某个 + Add 按钮时调用了 setFieldsValue 加了一个 item 进去,页面也不会更新。 |
交互不太直观,但是听起来需求是合理的。 |
我感觉应该是 ok 的,这个改动不影响现有设计和实现,不会给未来留坑,让 useWatch 符合了 preserve 的预期,甚至还有性能提升(传入 true 会直接返回 store 引用而不是经过处理)😂 可以再举一个需求场景:有一个巨型表单页面,我们会因为性能问题而设计成“点击某个面板展开对应的表单区域”,那么未展开的区域内字段 watch 就不生效了。 |
逻辑我理一下,以防万一 |
想了想放 Form 的 |
不过这参数不太好传进 BTW,我发现当前的修改对于 |
可以是可变参数: Form.useWatch('name')
Form.useWatch('name', form)
Form.useWatch('name', { form, preserve: true }) |
另外 bug 的话一步一步来,分几个 PR 搞会清楚一些~ |
感觉把 与之类似的函数 |
Anyway,我先试着写一下,思路大概是这样,你看有没有什么问题:
|
@zombieJ 实现应该是没有问题的,不过调用方式我还是觉得加一个新的参数会比较好,就按照这样来写了😂 |
@zombieJ 这个仓库的 CI 好像偶尔不会跑,是要手动触发一下吗? |
新加参数容易变成参数地狱,如果未来 useWatch 又需要新的参数,而且又比 preserve 更重要,那也不得不放在 preserve 后面。对于 form 而言,本身是可选的,preserve 也是可选的,那就没有必要再一路加上去了。 |
first time contributor 需要 owner 手工点确认执行以防止有恶意代码注入,这个是 github 的安全机制。 |
虽然在函数签名中 之所以设计成三个参数,其实就是仿照 Form.useWatch('name', form, {
preserve: true,
passive: true,
}); |
只有和 Form 同级的时候才需要传入。如果是 Form 内部的组件,是会通过 context 获取 FormInstance 的: |
原来在上面还有个逻辑啊,我了解了,这就改一下。 |
可以了,为了判断参数类型(都是 Object),额外写了个 |
src/interface.ts
Outdated
|
||
export interface WatchItem { | ||
callback: WatchCallBack; | ||
options: WatchOptions; |
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.
这里以及下面的地方都是内部使用,如果可能的话我一般不会省略,这可以避免因为“改变数据结构/函数签名但漏改实现”而导致的问题。
数据结构还好,主要是函数签名,如果我有个地方忘记传 options
,ts 会帮我检验出这个问题,如果设置成可选的,ts 就帮不上忙了。
src/useForm.ts
Outdated
|
||
private registerWatch: InternalHooks['registerWatch'] = callback => { | ||
this.watchList.push(callback); | ||
private registerWatch: InternalHooks['registerWatch'] = (callback, options) => { |
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
里走一圈 options,本身就是 useWatch 的参数。在遍历 watchList
的时候 callback 带上保留值 和 全部 值即可,让 useWatch
自行处理:
this.watchList.forEach(callback => {
callback(values, 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.
有道理,这样 options 就被限制在 useWatch 里面了,我改一下~
antd 侧也需要给 feature 发个 PR 提升一下哈~ |
This comment was marked as resolved.
This comment was marked as resolved.
|
是的,抱歉,当时排查看到useWatch实现里的args定义里没有undefined,就以为是undefined带来的问题(不过定义是不是加上比较好?),没有再细看了。 |
The existing prop
preserve
inForm
is used to keep values even if the field is not rendered. However, it will not trigger thewatchList
because thegetFieldsValue
is called withouttrue
and will return only the visible fields.Form
目前已有的preserve
属性是用来在 field 没有被渲染的情况下依旧能获取值。但它不能触发watchList
,因为内部的getFieldsValue
在不传true
的情况下只会返回可见的 fields。