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
This commit is contained in:
xliez 2023-02-14 17:39:35 +08:00 committed by GitHub
parent e11ef765a1
commit 0d67bde239
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 189 additions and 0 deletions

View File

@ -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(
<ConfigProvider componentSize='small'>
<App />
</ConfigProvider>,
);
expect(size).toBe('small');
});
it('useConfig - componentDisabled', () => {
let disabled;
const App: React.FC = () => {
const { componentDisabled } = ConfigProvider.useConfig();
disabled = componentDisabled;
return null;
};
render(
<Form disabled>
<App />
</Form>,
);
expect(disabled).toBe(true);
});
it('deprecated SizeContext', () => {
resetWarned();
const App: React.FC = () => {
const { SizeContext } = ConfigProvider;
const ctx = React.useContext(SizeContext);
return <div>{ctx}</div>;
};
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
render(<App />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: ConfigProvider] ConfigProvider.SizeContext is deprecated. Please use `ConfigProvider.useConfig().componentSize` instead.',
);
errSpy.mockRestore();
});
});

View File

@ -0,0 +1,7 @@
## zh-CN
获取父级 `Provider` 的值。如 `DisabledContextProvider`、`SizeContextProvider`。
## en-US
Get the value of the parent `Provider`. Such as `DisabledContextProvider`, `SizeContextProvider`.

View File

@ -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 (
<>
<Form.Item label="componentSize value">
<Input value={componentSize} />
</Form.Item>
<Form.Item label="componentDisabled value">
<Input value={String(componentDisabled)} disabled={componentDisabled} />
</Form.Item>
</>
);
};
const App: React.FC = () => {
const [componentSize, setComponentSize] = useState<SizeType>('small');
const [disabled, setDisabled] = useState<boolean>(true);
return (
<div>
<Space>
<Radio.Group
value={componentSize}
onChange={(e) => {
setComponentSize(e.target.value);
}}
>
<Radio.Button value="small">Small</Radio.Button>
<Radio.Button value="middle">Middle</Radio.Button>
<Radio.Button value="large">Large</Radio.Button>
</Radio.Group>
<Checkbox checked={disabled} onChange={(e) => setDisabled(e.target.checked)}>
Form disabled
</Checkbox>
</Space>
<Divider />
<ConfigProvider componentSize={componentSize}>
<div className="example">
<Form disabled={disabled}>
<ConfigDisplay />
</Form>
</div>
</ConfigProvider>
</div>
);
};
export default App;

View File

@ -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;

View File

@ -43,6 +43,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p
<code src="./demo/size.tsx">Component size</code> <code src="./demo/size.tsx">Component size</code>
<code src="./demo/theme.tsx">Theme</code> <code src="./demo/theme.tsx">Theme</code>
<code src="./demo/prefixCls.tsx" debug>prefixCls</code> <code src="./demo/prefixCls.tsx" debug>prefixCls</code>
<code src="./demo/useConfig.tsx" debug>useConfig</code>
## API ## 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 ## FAQ
#### How to contribute a new language? #### How to contribute a new language?

View File

@ -22,6 +22,8 @@ import useTheme from './hooks/useTheme';
import type { SizeType } from './SizeContext'; import type { SizeType } from './SizeContext';
import SizeContext, { SizeContextProvider } from './SizeContext'; import SizeContext, { SizeContextProvider } from './SizeContext';
import useStyle from './style'; import useStyle from './style';
import useConfig from './hooks/useConfig';
import warning from '../_util/warning';
export { export {
type RenderEmptyHandler, type RenderEmptyHandler,
@ -311,8 +313,10 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
const ConfigProvider: React.FC<ConfigProviderProps> & { const ConfigProvider: React.FC<ConfigProviderProps> & {
/** @private internal Usage. do not use in your production */ /** @private internal Usage. do not use in your production */
ConfigContext: typeof ConfigContext; ConfigContext: typeof ConfigContext;
/** @deprecated Please use `ConfigProvider.useConfig().componentSize` instead */
SizeContext: typeof SizeContext; SizeContext: typeof SizeContext;
config: typeof setGlobalConfig; config: typeof setGlobalConfig;
useConfig: typeof useConfig;
} = (props) => ( } = (props) => (
<LocaleReceiver> <LocaleReceiver>
{(_, __, legacyLocale) => ( {(_, __, legacyLocale) => (
@ -328,6 +332,18 @@ const ConfigProvider: React.FC<ConfigProviderProps> & {
ConfigProvider.ConfigContext = ConfigContext; ConfigProvider.ConfigContext = ConfigContext;
ConfigProvider.SizeContext = SizeContext; ConfigProvider.SizeContext = SizeContext;
ConfigProvider.config = setGlobalConfig; 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') { if (process.env.NODE_ENV !== 'production') {
ConfigProvider.displayName = 'ConfigProvider'; ConfigProvider.displayName = 'ConfigProvider';

View File

@ -44,6 +44,7 @@ export default Demo;
<code src="./demo/size.tsx">组件尺寸</code> <code src="./demo/size.tsx">组件尺寸</code>
<code src="./demo/theme.tsx">主题</code> <code src="./demo/theme.tsx">主题</code>
<code src="./demo/prefixCls.tsx" debug>前缀</code> <code src="./demo/prefixCls.tsx" debug>前缀</code>
<code src="./demo/useConfig.tsx" debug>useConfig</code>
## API ## 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();
```
<!-- prettier-ignore -->
| 返回值 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| componentDisabled | antd 组件禁用状态 | boolean | - | 5.3.0 |
| componentSize | antd 组件大小状态 | `small` \| `middle` \| `large` | - | 5.3.0 |
## FAQ ## FAQ
#### 如何增加一个新的语言包? #### 如何增加一个新的语言包?