From 27b6ba694731284c8e8b100aebeebcc1a5bcaf87 Mon Sep 17 00:00:00 2001 From: 07akioni <07akioni2@gmail.com> Date: Fri, 3 Jul 2020 16:25:29 +0800 Subject: [PATCH] feat: form item dep (#25408) * feat: warnings * feat: deps work on FormItem with render props * chore: add details warning info * chore * chore: rerun ci * chore: revert * docs * docs --- components/form/FormItem.tsx | 14 +++- .../__tests__/__snapshots__/demo.test.js.snap | 75 +++++++++++++++++++ components/form/__tests__/index.test.js | 14 +++- components/form/demo/dep-debug.md | 49 ++++++++++++ components/form/index.en-US.md | 4 + components/form/index.zh-CN.md | 4 + package.json | 2 +- 7 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 components/form/demo/dep-debug.md diff --git a/components/form/FormItem.tsx b/components/form/FormItem.tsx index 317e265cce..b57ea282cc 100644 --- a/components/form/FormItem.tsx +++ b/components/form/FormItem.tsx @@ -299,14 +299,20 @@ function FormItem(props: FormItemProps): React.ReactElement { }; let childNode: React.ReactNode = null; + + devWarning( + !(shouldUpdate && dependencies), + 'Form.Item', + "`shouldUpdate` and `dependencies` shouldn't be used together. See https://ant.design/components/form/#dependencies.", + ); if (Array.isArray(children) && hasName) { devWarning(false, 'Form.Item', '`children` is array of render props cannot have `name`.'); childNode = children; - } else if (isRenderProps && (!shouldUpdate || hasName)) { + } else if (isRenderProps && (!(shouldUpdate || dependencies) || hasName)) { devWarning( - !!shouldUpdate, + !!(shouldUpdate || dependencies), 'Form.Item', - '`children` of render props only work with `shouldUpdate`.', + '`children` of render props only work with `shouldUpdate` or `dependencies`.', ); devWarning( !hasName, @@ -356,7 +362,7 @@ function FormItem(props: FormItemProps): React.ReactElement { {cloneElement(children, childProps)} ); - } else if (isRenderProps && shouldUpdate && !hasName) { + } else if (isRenderProps && (shouldUpdate || dependencies) && !hasName) { childNode = (children as RenderChildren)(context); } else { devWarning( diff --git a/components/form/__tests__/__snapshots__/demo.test.js.snap b/components/form/__tests__/__snapshots__/demo.test.js.snap index f974331ef2..15e838cbe3 100644 --- a/components/form/__tests__/__snapshots__/demo.test.js.snap +++ b/components/form/__tests__/__snapshots__/demo.test.js.snap @@ -1449,6 +1449,81 @@ exports[`renders ./components/form/demo/disabled-input-debug.md correctly 1`] = `; +exports[`renders ./components/form/demo/dep-debug.md correctly 1`] = ` +
+ 0 +
+
+ +
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+`; + exports[`renders ./components/form/demo/dynamic-form-item.md correctly 1`] = `
{
, ); expect(errorSpy).toHaveBeenCalledWith( - 'Warning: [antd: Form.Item] `children` of render props only work with `shouldUpdate`.', + 'Warning: [antd: Form.Item] `children` of render props only work with `shouldUpdate` or `dependencies`.', + ); + }); + it("`shouldUpdate` shouldn't work with `dependencies`", () => { + mount( +
+ + {() => null} + +
, + ); + expect(errorSpy).toHaveBeenCalledWith( + "Warning: [antd: Form.Item] `shouldUpdate` and `dependencies` shouldn't be used together. See https://ant.design/components/form/#dependencies.", ); }); it('`name` should not work with render props', () => { diff --git a/components/form/demo/dep-debug.md b/components/form/demo/dep-debug.md new file mode 100644 index 0000000000..19371cef20 --- /dev/null +++ b/components/form/demo/dep-debug.md @@ -0,0 +1,49 @@ +--- +order: 99 +title: + zh-CN: Dep Debug + en-US: Dep Debug +--- + +## zh-CN + +Buggy! + +## en-US + +Buggy! + +```tsx +import { Form, Input } from 'antd'; + +let acc = 0; + +const Demo = () => { + const [form] = Form.useForm(); + return ( +
+ + {() => { + return acc++; + // return
{JSON.stringify(form.getFieldsValue(), null, 2)}
; + }} +
+ + + + + + +
+ ); +}; + +ReactDOM.render(, mountNode); +``` diff --git a/components/form/index.en-US.md b/components/form/index.en-US.md index 9846467407..372881229d 100644 --- a/components/form/index.en-US.md +++ b/components/form/index.en-US.md @@ -109,6 +109,10 @@ After wrapped by `Form.Item` with `name` property, `value`(or other property def Used when there are dependencies between fields. If a field has the `dependencies` prop, this field will automatically trigger updates and validations when upstream is updated. A common scenario is a user registration form with "password" and "confirm password" fields. The "Confirm Password" validation depends on the "Password" field. After setting `dependencies`, the "Password" field update will re-trigger the validation of "Check Password". You can refer [examples](#components-form-demo-register). +`dependencies` shouldn't be used together with `shouldUpdate`. Since it may cause chaos in updating logic. + +`dependencies` supports `Form.Item` with render props children since `4.5.0`. + ### shouldUpdate Form updates only the modified field-related components for performance optimization purposes by incremental update. In most cases, you only need to write code or do validation with the [`dependencies`](#dependencies) property. In some specific cases, such as when a new field option appears with a filed value changed, or you just want to keep some area updating by form update, you can modify the update logic of Form.Item via the `shouldUpdate`. diff --git a/components/form/index.zh-CN.md b/components/form/index.zh-CN.md index dd041dec77..05746d8faa 100644 --- a/components/form/index.zh-CN.md +++ b/components/form/index.zh-CN.md @@ -110,6 +110,10 @@ const validateMessages = { 当字段间存在依赖关系时使用。如果一个字段设置了 `dependencies` 属性。那么它所依赖的字段更新时,该字段将自动触发更新与校验。一种常见的场景,就是注册用户表单的“密码”与“确认密码”字段。“确认密码”校验依赖于“密码”字段,设置 `dependencies` 后,“密码”字段更新会重新触发“校验密码”的校验逻辑。你可以参考[具体例子](#components-form-demo-register)。 +`dependencies` 不应和 `shouldUpdate` 一起使用,因为这可能带来更新逻辑的混乱。 + +从 `4.5.0` 版本开始,`dependencies` 支持使用 render props 类型 children 的 `Form.Item`。 + ### shouldUpdate Form 通过增量更新方式,只更新被修改的字段相关组件以达到性能优化目的。大部分场景下,你只需要编写代码或者与 [`dependencies`](#dependencies) 属性配合校验即可。而在某些特定场景,例如修改某个字段值后出现新的字段选项、或者纯粹希望表单任意变化都对某一个区域进行渲染。你可以通过 `shouldUpdate` 修改 Form.Item 的更新逻辑。 diff --git a/package.json b/package.json index 737b40ca85..226b9a530f 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "rc-dialog": "~8.0.0", "rc-drawer": "~4.1.0", "rc-dropdown": "~3.1.2", - "rc-field-form": "~1.6.0", + "rc-field-form": "~1.7.0", "rc-input-number": "~5.1.0", "rc-mentions": "~1.3.0", "rc-menu": "~8.3.0",