From 0d67bde2398723c6f7c033cb771892001957c5c9 Mon Sep 17 00:00:00 2001 From: xliez Date: Tue, 14 Feb 2023 17:39:35 +0800 Subject: [PATCH] feat: add useConfig hook to ConfigProvider (#40215) * feat: add useConfig hook to ConfigProvider * docs: format config-provide markdown * doc: add available version * test: add useConfig test * docs: add debug * chore: fix lint error * fix: getter dead loop * test: promote useConfig test coverage * docs(ConfigProvider): update available version --- .../__tests__/useConfig.test.tsx | 63 +++++++++++++++++++ components/config-provider/demo/useConfig.md | 7 +++ components/config-provider/demo/useConfig.tsx | 53 ++++++++++++++++ components/config-provider/hooks/useConfig.ts | 15 +++++ components/config-provider/index.en-US.md | 17 +++++ components/config-provider/index.tsx | 16 +++++ components/config-provider/index.zh-CN.md | 18 ++++++ 7 files changed, 189 insertions(+) create mode 100644 components/config-provider/__tests__/useConfig.test.tsx create mode 100644 components/config-provider/demo/useConfig.md create mode 100644 components/config-provider/demo/useConfig.tsx create mode 100644 components/config-provider/hooks/useConfig.ts diff --git a/components/config-provider/__tests__/useConfig.test.tsx b/components/config-provider/__tests__/useConfig.test.tsx new file mode 100644 index 0000000000..0e1413b3bf --- /dev/null +++ b/components/config-provider/__tests__/useConfig.test.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import ConfigProvider from '..'; +import Form from '../../form'; +import { render } from '../../../tests/utils'; +import { resetWarned } from '../../_util/warning'; + +describe('ConfigProvider.useConfig', () => { + it('useConfig - componentSize', () => { + let size; + + const App: React.FC = () => { + const { componentSize } = ConfigProvider.useConfig(); + size = componentSize; + + return null; + }; + + render( + + + , + ); + + expect(size).toBe('small'); + }); + + it('useConfig - componentDisabled', () => { + let disabled; + const App: React.FC = () => { + const { componentDisabled } = ConfigProvider.useConfig(); + disabled = componentDisabled; + return null; + }; + + render( +
+ + , + ); + + expect(disabled).toBe(true); + }); + + it('deprecated SizeContext', () => { + resetWarned(); + + const App: React.FC = () => { + const { SizeContext } = ConfigProvider; + const ctx = React.useContext(SizeContext); + + return
{ctx}
; + }; + + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + + render(); + + expect(errSpy).toHaveBeenCalledWith( + 'Warning: [antd: ConfigProvider] ConfigProvider.SizeContext is deprecated. Please use `ConfigProvider.useConfig().componentSize` instead.', + ); + errSpy.mockRestore(); + }); +}); diff --git a/components/config-provider/demo/useConfig.md b/components/config-provider/demo/useConfig.md new file mode 100644 index 0000000000..f13789336c --- /dev/null +++ b/components/config-provider/demo/useConfig.md @@ -0,0 +1,7 @@ +## zh-CN + +获取父级 `Provider` 的值。如 `DisabledContextProvider`、`SizeContextProvider`。 + +## en-US + +Get the value of the parent `Provider`. Such as `DisabledContextProvider`, `SizeContextProvider`. diff --git a/components/config-provider/demo/useConfig.tsx b/components/config-provider/demo/useConfig.tsx new file mode 100644 index 0000000000..e7f7264752 --- /dev/null +++ b/components/config-provider/demo/useConfig.tsx @@ -0,0 +1,53 @@ +import React, { useState } from 'react'; +import { Checkbox, ConfigProvider, Divider, Form, Input, Radio, Space } from 'antd'; +import type { SizeType } from 'antd/es/config-provider/SizeContext'; + +const ConfigDisplay = () => { + const { componentDisabled, componentSize } = ConfigProvider.useConfig(); + + return ( + <> + + + + + + + + ); +}; + +const App: React.FC = () => { + const [componentSize, setComponentSize] = useState('small'); + const [disabled, setDisabled] = useState(true); + + return ( +
+ + { + setComponentSize(e.target.value); + }} + > + Small + Middle + Large + + setDisabled(e.target.checked)}> + Form disabled + + + + +
+
+ + +
+
+
+ ); +}; + +export default App; diff --git a/components/config-provider/hooks/useConfig.ts b/components/config-provider/hooks/useConfig.ts new file mode 100644 index 0000000000..10f8ed6398 --- /dev/null +++ b/components/config-provider/hooks/useConfig.ts @@ -0,0 +1,15 @@ +import { useContext } from 'react'; +import DisabledContext from '../DisabledContext'; +import SizeContext from '../SizeContext'; + +function useConfig() { + const componentDisabled = useContext(DisabledContext); + const componentSize = useContext(SizeContext); + + return { + componentDisabled, + componentSize, + }; +} + +export default useConfig; diff --git a/components/config-provider/index.en-US.md b/components/config-provider/index.en-US.md index 573e1a86f0..467b8b741c 100644 --- a/components/config-provider/index.en-US.md +++ b/components/config-provider/index.en-US.md @@ -43,6 +43,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p Component size Theme prefixCls +useConfig ## API @@ -78,6 +79,22 @@ ConfigProvider.config({ }); ``` +### ConfigProvider.useConfig() `5.3.0+` + +Available since `5.2.0`. Get the value of the parent `Provider`. Such as `DisabledContextProvider`, `SizeContextProvider`. + +```jsx +const { + componentDisabled, // 5.3.0+ + componentSize, // 5.3.0+ +} = ConfigProvider.useConfig(); +``` + +| 返回值 | 说明 | 类型 | 默认值 | 版本 | +| --- | --- | --- | --- | --- | +| componentDisabled | antd component disabled state | boolean | - | 5.3.0 | +| componentSize | antd component size state | `small` \| `middle` \| `large` | - | 5.3.0 | + ## FAQ #### How to contribute a new language? diff --git a/components/config-provider/index.tsx b/components/config-provider/index.tsx index 671652c501..d3e20a0dac 100644 --- a/components/config-provider/index.tsx +++ b/components/config-provider/index.tsx @@ -22,6 +22,8 @@ import useTheme from './hooks/useTheme'; import type { SizeType } from './SizeContext'; import SizeContext, { SizeContextProvider } from './SizeContext'; import useStyle from './style'; +import useConfig from './hooks/useConfig'; +import warning from '../_util/warning'; export { type RenderEmptyHandler, @@ -311,8 +313,10 @@ const ProviderChildren: React.FC = (props) => { const ConfigProvider: React.FC & { /** @private internal Usage. do not use in your production */ ConfigContext: typeof ConfigContext; + /** @deprecated Please use `ConfigProvider.useConfig().componentSize` instead */ SizeContext: typeof SizeContext; config: typeof setGlobalConfig; + useConfig: typeof useConfig; } = (props) => ( {(_, __, legacyLocale) => ( @@ -328,6 +332,18 @@ const ConfigProvider: React.FC & { ConfigProvider.ConfigContext = ConfigContext; ConfigProvider.SizeContext = SizeContext; ConfigProvider.config = setGlobalConfig; +ConfigProvider.useConfig = useConfig; + +Object.defineProperty(ConfigProvider, 'SizeContext', { + get: () => { + warning( + false, + 'ConfigProvider', + 'ConfigProvider.SizeContext is deprecated. Please use `ConfigProvider.useConfig().componentSize` instead.', + ); + return SizeContext; + }, +}); if (process.env.NODE_ENV !== 'production') { ConfigProvider.displayName = 'ConfigProvider'; diff --git a/components/config-provider/index.zh-CN.md b/components/config-provider/index.zh-CN.md index ca2d047505..2b91f7437c 100644 --- a/components/config-provider/index.zh-CN.md +++ b/components/config-provider/index.zh-CN.md @@ -44,6 +44,7 @@ export default Demo; 组件尺寸 主题 前缀 +useConfig ## API @@ -79,6 +80,23 @@ ConfigProvider.config({ }); ``` +### ConfigProvider.useConfig() `5.3.0+` + +`5.2.0` 版本后可用。获取父级 `Provider` 的值。如 `DisabledContextProvider`、`SizeContextProvider`。 + +```jsx +const { + componentDisabled, // 5.3.0+ + componentSize, // 5.3.0+ +} = ConfigProvider.useConfig(); +``` + + +| 返回值 | 说明 | 类型 | 默认值 | 版本 | +| --- | --- | --- | --- | --- | +| componentDisabled | antd 组件禁用状态 | boolean | - | 5.3.0 | +| componentSize | antd 组件大小状态 | `small` \| `middle` \| `large` | - | 5.3.0 | + ## FAQ #### 如何增加一个新的语言包?