From 917e41ecc510800255a5c103ba7690f6ac41c56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Tue, 9 May 2023 19:09:21 +0800 Subject: [PATCH] docs: update faq (#42233) --- .eslintrc.js | 2 +- components/form/Form.tsx | 6 ++++++ components/form/__tests__/index.test.tsx | 15 +++++++++++++++ components/form/hooks/useFormWarning.ts | 19 +++++++++++++++++++ components/form/index.en-US.md | 4 ++++ components/form/index.zh-CN.md | 4 ++++ 6 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 components/form/hooks/useFormWarning.ts diff --git a/.eslintrc.js b/.eslintrc.js index 12628ed2b1..5e01410968 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -189,7 +189,7 @@ module.exports = { 'unicorn/better-regex': 2, 'unicorn/prefer-string-trim-start-end': 2, 'unicorn/expiring-todo-comments': 2, - 'unicorn/no-abusive-eslint-disable': 2, + 'unicorn/no-abusive-eslint-disable': 0, // https://github.com/typescript-eslint/typescript-eslint/issues/2540#issuecomment-692866111 'no-use-before-define': 0, diff --git a/components/form/Form.tsx b/components/form/Form.tsx index d18a7ac943..d4c6e99ad9 100644 --- a/components/form/Form.tsx +++ b/components/form/Form.tsx @@ -15,6 +15,7 @@ import { FormContext } from './context'; import useForm, { type FormInstance } from './hooks/useForm'; import type { FormLabelAlign } from './interface'; +import useFormWarning from './hooks/useFormWarning'; import useStyle from './style'; export type RequiredMark = boolean | 'optional'; @@ -65,6 +66,11 @@ const InternalForm: React.ForwardRefRenderFunction = (p ...restFormProps } = props; + if (process.env.NODE_ENV !== 'production') { + // eslint-disable-next-line react-hooks/rules-of-hooks + useFormWarning(props); + } + const mergedRequiredMark = useMemo(() => { if (requiredMark !== undefined) { return requiredMark; diff --git a/components/form/__tests__/index.test.tsx b/components/form/__tests__/index.test.tsx index 0817b90e95..e7f0fa8c62 100644 --- a/components/form/__tests__/index.test.tsx +++ b/components/form/__tests__/index.test.tsx @@ -1878,4 +1878,19 @@ describe('Form', () => { expect(container.querySelectorAll('input')[1].value).toEqual('14'); expect(errorSpy).not.toHaveBeenCalled(); }); + + it('duplicated form name', () => { + resetWarned(); + + render( + <> +
+ + , + ); + + expect(errorSpy).toHaveBeenCalledWith( + 'Warning: [antd: Form] There exist multiple Form with same `name`.', + ); + }); }); diff --git a/components/form/hooks/useFormWarning.ts b/components/form/hooks/useFormWarning.ts new file mode 100644 index 0000000000..4f3d69fe26 --- /dev/null +++ b/components/form/hooks/useFormWarning.ts @@ -0,0 +1,19 @@ +import { useEffect } from 'react'; +import warning from '../../_util/warning'; +import type { FormProps } from '../Form'; + +const names: Record = {}; + +export default function useFormWarning({ name }: FormProps) { + useEffect(() => { + if (name) { + names[name] = (names[name] || 0) + 1; + + warning(names[name] <= 1, 'Form', 'There exist multiple Form with same `name`.'); + + return () => { + names[name] -= 1; + }; + } + }, [name]); +} diff --git a/components/form/index.en-US.md b/components/form/index.en-US.md index ce4d7d6918..49702a62a7 100644 --- a/components/form/index.en-US.md +++ b/components/form/index.en-US.md @@ -593,6 +593,10 @@ See similar issues: [#28370](https://github.com/ant-design/ant-design/issues/283 `scrollToFirstError` and `scrollToField` deps on `id` attribute passed to form control, please make sure that it hasn't been ignored in your custom form control. Check [codesandbox](https://codesandbox.io/s/antd-reproduction-template-forked-25nul?file=/index.js) for solution. +### Continue, why not use `ref` to bind element? + +Form can not get real DOM node when customize component not support `ref`. It will get warning in React Strict Mode if wrap with Class Component and call `findDOMNode`. So we use `id` to locate element. + ### `setFieldsValue` do not trigger `onFieldsChange` or `onValuesChange`? It's by design. Only user interactive can trigger the change event. This design is aim to avoid call `setFieldsValue` in change event which may makes loop calling. diff --git a/components/form/index.zh-CN.md b/components/form/index.zh-CN.md index 3fc0c225c4..911c1a226a 100644 --- a/components/form/index.zh-CN.md +++ b/components/form/index.zh-CN.md @@ -592,6 +592,10 @@ React 中异步更新会导致受控组件交互行为异常。当用户交互 滚动依赖于表单控件元素上绑定的 `id` 字段,如果自定义控件没有将 `id` 赋到正确的元素上,这个功能将失效。你可以参考这个 [codesandbox](https://codesandbox.io/s/antd-reproduction-template-forked-25nul?file=/index.js)。 +### 继上,为何不通过 `ref` 绑定元素? + +当自定义组件不支持 `ref` 时,Form 无法获取子元素真实 DOM 节点,而通过包裹 Class Component 调用 `findDOMNode` 会在 React Strict Mode 下触发警告。因而我们使用 id 来进行元素定位。 + ### `setFieldsValue` 不会触发 `onFieldsChange` 和 `onValuesChange`? 是的,change 事件仅当用户交互才会触发。该设计是为了防止在 change 事件中调用 `setFieldsValue` 导致的循环问题。如果仅仅需要组件内消费,可以通过 `useWatch` 或者 `Field.renderProps` 来实现。