From 184402a9bcc8819ad53b2538c547b35abb6517cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Fri, 29 Oct 2021 18:24:50 +0800 Subject: [PATCH] feat: Form.Item no longer need `fieldKey` anymore (#32689) * chore:Update Form to remove fieldKey * fix: fieldKey cache logic * test: Update snapshot * chore: clean up --- components/form/FormItem.tsx | 28 ++++- components/form/FormList.tsx | 13 +-- .../__tests__/__snapshots__/demo.test.js.snap | 106 ++++++++++++++++++ .../form/__tests__/list-noStyle.test.tsx | 1 - .../form/demo/dynamic-form-items-complex.md | 2 - .../form/demo/dynamic-form-items-no-style.md | 66 +++++++++++ components/form/demo/dynamic-form-items.md | 8 +- package.json | 2 +- 8 files changed, 202 insertions(+), 24 deletions(-) create mode 100644 components/form/demo/dynamic-form-items-no-style.md diff --git a/components/form/FormItem.tsx b/components/form/FormItem.tsx index 68e12fe9f8..bdcbb5e366 100644 --- a/components/form/FormItem.tsx +++ b/components/form/FormItem.tsx @@ -1,9 +1,8 @@ import * as React from 'react'; import { useContext } from 'react'; import classNames from 'classnames'; -import { Field, FormInstance } from 'rc-field-form'; +import { Field, FormInstance, FieldContext, ListContext } from 'rc-field-form'; import { FieldProps } from 'rc-field-form/lib/Field'; -import FieldContext from 'rc-field-form/lib/FieldContext'; import { Meta, NamePath } from 'rc-field-form/lib/interface'; import { supportRef } from 'rc-util/lib/ref'; import omit from 'rc-util/lib/omit'; @@ -62,7 +61,7 @@ export interface FormItemProps initialValue?: any; messageVariables?: Record; tooltip?: LabelTooltipType; - /** Auto passed by List render props. User should not use this. */ + /** @deprecated No need anymore */ fieldKey?: React.Key | React.Key[]; } @@ -86,7 +85,6 @@ function genEmptyMeta(): Meta { function FormItem(props: FormItemProps): React.ReactElement { const { name, - fieldKey, noStyle, dependencies, prefixCls: customizePrefixCls, @@ -119,6 +117,11 @@ function FormItem(props: FormItemProps): React.ReactElemen const prefixCls = getPrefixCls('form', customizePrefixCls); + // ========================= MISC ========================= + // Get `noStyle` required info + const listContext = React.useContext(ListContext); + const fieldKeyPathRef = React.useRef(); + // ======================== Errors ======================== // >>>>> Collect sub field errors const [subFieldErrors, setSubFieldErrors] = useFrameState>({}); @@ -127,14 +130,27 @@ function FormItem(props: FormItemProps): React.ReactElemen const [meta, setMeta] = React.useState(() => genEmptyMeta()); const onMetaChange = (nextMeta: Meta & { destroy?: boolean }) => { + // This keyInfo is not correct when field is removed + // Since origin keyManager no longer keep the origin key anymore + // Which means we need cache origin one and reuse when removed + const keyInfo = listContext?.getKey(nextMeta.name); + // Destroy will reset all the meta setMeta(nextMeta.destroy ? genEmptyMeta() : nextMeta); // Bump to parent since noStyle if (noStyle && notifyParentMetaChange) { let namePath = nextMeta.name; - if (fieldKey !== undefined) { - namePath = Array.isArray(fieldKey) ? fieldKey : [fieldKey!]; + + if (!nextMeta.destroy) { + if (keyInfo !== undefined) { + const [fieldKey, restPath] = keyInfo; + namePath = [fieldKey, ...restPath]; + fieldKeyPathRef.current = namePath; + } + } else { + // Use origin cache data + namePath = fieldKeyPathRef.current || namePath; } notifyParentMetaChange(nextMeta, namePath); } diff --git a/components/form/FormList.tsx b/components/form/FormList.tsx index 477ec365c6..d47f7e0741 100644 --- a/components/form/FormList.tsx +++ b/components/form/FormList.tsx @@ -8,7 +8,6 @@ import { FormItemPrefixContext } from './context'; export interface FormListFieldData { name: number; key: number; - fieldKey: number; } export interface FormListOperation { @@ -43,14 +42,10 @@ const FormList: React.FC = ({ {(fields, operation, meta) => ( - {children( - fields.map(field => ({ ...field, fieldKey: field.key })), - operation, - { - errors: meta.errors, - warnings: meta.warnings, - }, - )} + {children(fields, operation, { + errors: meta.errors, + warnings: meta.warnings, + })} )} diff --git a/components/form/__tests__/__snapshots__/demo.test.js.snap b/components/form/__tests__/__snapshots__/demo.test.js.snap index 07950519af..ff56198a9f 100644 --- a/components/form/__tests__/__snapshots__/demo.test.js.snap +++ b/components/form/__tests__/__snapshots__/demo.test.js.snap @@ -1904,6 +1904,112 @@ exports[`renders ./components/form/demo/dynamic-form-items-complex.md correctly `; +exports[`renders ./components/form/demo/dynamic-form-items-no-style.md correctly 1`] = ` +
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+`; + exports[`renders ./components/form/demo/dynamic-rule.md correctly 1`] = `
{ diff --git a/components/form/demo/dynamic-form-items-complex.md b/components/form/demo/dynamic-form-items-complex.md index 08bdeecd5a..1fccb94240 100644 --- a/components/form/demo/dynamic-form-items-complex.md +++ b/components/form/demo/dynamic-form-items-complex.md @@ -61,7 +61,6 @@ const Demo = () => { {...field} label="Sight" name={[field.name, 'sight']} - fieldKey={[field.fieldKey, 'sight']} rules={[{ required: true, message: 'Missing sight' }]} > diff --git a/components/form/demo/dynamic-form-items-no-style.md b/components/form/demo/dynamic-form-items-no-style.md new file mode 100644 index 0000000000..2a87a0daef --- /dev/null +++ b/components/form/demo/dynamic-form-items-no-style.md @@ -0,0 +1,66 @@ +--- +order: 4.11 +title: + zh-CN: 动态增减嵌套纯字段 + en-US: Dynamic Form nest pure Items +debug: true +--- + +## zh-CN + +嵌套 `noStyle` 字段的动态表单示例。 + +## en-US + +Nest with `noStyle` field dynamic form. + +```jsx +import { Form, Input, Button, Space } from 'antd'; +import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; + +const Demo = () => { + const onFinish = values => { + console.log('Received values of form:', values); + }; + + return ( + + + + {(fields, { add, remove }) => ( + <> + {fields.map(field => ( + + + + + + + + { + remove(field.name); + }} + /> + + ))} + + + + + )} + + + + + + + ); +}; + +ReactDOM.render(, mountNode); +``` diff --git a/components/form/demo/dynamic-form-items.md b/components/form/demo/dynamic-form-items.md index a99787743d..524d482c7c 100644 --- a/components/form/demo/dynamic-form-items.md +++ b/components/form/demo/dynamic-form-items.md @@ -7,11 +7,11 @@ title: ## zh-CN -嵌套表单字段需要对 `field` 进行拓展,将 `field.name` 和 `field.fieldKey` 应用于控制字段。 +嵌套表单字段需要对 `field` 进行拓展,将 `field.name` 应用于控制字段。 ## en-US -Nest dynamic field need extends `field`. Pass `field.name` and `field.fieldKey` to nest item. +Nest dynamic field need extends `field`. Pass `field.name` to nest item. ```jsx import { Form, Input, Button, Space } from 'antd'; @@ -27,12 +27,11 @@ const Demo = () => { {(fields, { add, remove }) => ( <> - {fields.map(({ key, name, fieldKey, ...restField }) => ( + {fields.map(({ key, name, ...restField }) => ( @@ -40,7 +39,6 @@ const Demo = () => { diff --git a/package.json b/package.json index c4a95f0fba..04824852ac 100644 --- a/package.json +++ b/package.json @@ -124,7 +124,7 @@ "rc-dialog": "~8.6.0", "rc-drawer": "~4.4.2", "rc-dropdown": "~3.2.0", - "rc-field-form": "~1.21.0", + "rc-field-form": "~1.22.0-2", "rc-image": "~5.2.5", "rc-input-number": "~7.3.0", "rc-mentions": "~1.6.1",