mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
feat: ConfigProvider support config warning level (#44809)
* test: add test case * chore: use console.warn instead * chore: support agg * chore: fix lint
This commit is contained in:
parent
a24b30c77e
commit
b3428c678f
@ -1,9 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import rcWarning, { resetWarned } from 'rc-util/lib/warning';
|
||||
import rcWarning, { resetWarned as rcResetWarned } from 'rc-util/lib/warning';
|
||||
|
||||
export { resetWarned };
|
||||
export function noop() {}
|
||||
|
||||
let deprecatedWarnList: Record<string, string[]> | null = null;
|
||||
|
||||
export function resetWarned() {
|
||||
deprecatedWarnList = null;
|
||||
rcResetWarned();
|
||||
}
|
||||
|
||||
type Warning = (valid: boolean, component: string, message?: string) => void;
|
||||
|
||||
// eslint-disable-next-line import/no-mutable-exports
|
||||
@ -32,7 +38,7 @@ type TypeWarning = (
|
||||
) => void;
|
||||
|
||||
export interface WarningContextProps {
|
||||
deprecated?: boolean;
|
||||
strict?: boolean;
|
||||
}
|
||||
|
||||
export const WarningContext = React.createContext<WarningContextProps>({});
|
||||
@ -45,11 +51,33 @@ export const WarningContext = React.createContext<WarningContextProps>({});
|
||||
export const devUseWarning: () => TypeWarning =
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? () => {
|
||||
const { deprecated } = React.useContext(WarningContext);
|
||||
const { strict } = React.useContext(WarningContext);
|
||||
|
||||
const typeWarning: TypeWarning = (valid, component, type, message) => {
|
||||
if (deprecated !== false || type !== 'deprecated') {
|
||||
warning(valid, component, message);
|
||||
if (!valid) {
|
||||
if (strict === false && type === 'deprecated') {
|
||||
const existWarning = deprecatedWarnList;
|
||||
|
||||
if (!deprecatedWarnList) {
|
||||
deprecatedWarnList = {};
|
||||
}
|
||||
|
||||
deprecatedWarnList[component] = deprecatedWarnList[component] || [];
|
||||
if (!deprecatedWarnList[component].includes(message || '')) {
|
||||
deprecatedWarnList[component].push(message || '');
|
||||
}
|
||||
|
||||
// Warning for the first time
|
||||
if (!existWarning) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'[antd] There exists deprecated usage in your code:',
|
||||
deprecatedWarnList,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
warning(valid, component, message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -139,7 +139,7 @@ const InternalAvatar: React.ForwardRefRenderFunction<HTMLSpanElement, AvatarProp
|
||||
warning(
|
||||
!(typeof icon === 'string' && icon.length > 2),
|
||||
'Avatar',
|
||||
'deprecated',
|
||||
'breaking',
|
||||
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`,
|
||||
);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { SmileOutlined } from '@ant-design/icons';
|
||||
|
||||
import type { ConfigConsumerProps, RenderEmptyHandler } from '..';
|
||||
import ConfigProvider, { ConfigContext } from '..';
|
||||
import { resetWarned } from '../../_util/warning';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
@ -124,4 +125,17 @@ describe('ConfigProvider', () => {
|
||||
expect(rendered).toBeTruthy();
|
||||
expect(cacheRenderEmpty).toBeFalsy();
|
||||
});
|
||||
|
||||
it('warning support filter level', () => {
|
||||
resetWarned();
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
render(<ConfigProvider dropdownMatchSelectWidth warning={{ strict: false }} />);
|
||||
expect(errSpy).not.toHaveBeenCalled();
|
||||
expect(warnSpy).toHaveBeenCalled();
|
||||
|
||||
errSpy.mockRestore();
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
7
components/config-provider/demo/warning.md
Normal file
7
components/config-provider/demo/warning.md
Normal file
@ -0,0 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
调整 warning 策略。
|
||||
|
||||
## en-US
|
||||
|
||||
Adjust warning strategy.
|
14
components/config-provider/demo/warning.tsx
Normal file
14
components/config-provider/demo/warning.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import { Alert, ConfigProvider, Input, Typography } from 'antd';
|
||||
|
||||
const App: React.FC = () => (
|
||||
<>
|
||||
<Typography.Title level={4}>Open single page to check the console</Typography.Title>
|
||||
<ConfigProvider warning={{ strict: false }}>
|
||||
<Alert closeText="deprecated" />
|
||||
<Input.Group />
|
||||
</ConfigProvider>
|
||||
</>
|
||||
);
|
||||
|
||||
export default App;
|
@ -13,8 +13,8 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*YC4ERpGAddoAAA
|
||||
This component provides a configuration to all React components underneath itself via the [context API](https://facebook.github.io/react/docs/context.html). In the render tree all components will have access to the provided config.
|
||||
|
||||
```tsx
|
||||
import { ConfigProvider } from 'antd';
|
||||
import React from 'react';
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
// ...
|
||||
const Demo: React.FC = () => (
|
||||
@ -46,6 +46,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p
|
||||
<code src="./demo/wave.tsx">Custom Wave</code>
|
||||
<code src="./demo/prefixCls.tsx" debug>prefixCls</code>
|
||||
<code src="./demo/useConfig.tsx" debug>useConfig</code>
|
||||
<code src="./demo/warning.tsx" debug>warning</code>
|
||||
|
||||
## API
|
||||
|
||||
@ -66,6 +67,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p
|
||||
| renderEmpty | Set empty content of components. Ref [Empty](/components/empty/) | function(componentName: string): ReactNode | - | |
|
||||
| theme | Set theme, ref [Customize Theme](/docs/react/customize-theme) | - | - | 5.0.0 |
|
||||
| virtual | Disable virtual scroll when set to `false` | boolean | - | 4.3.0 |
|
||||
| warning | Config warning level, when `strict` is `false`, it will aggregate deprecated information into a single message | { strict: boolean } | - | 5.10.0 |
|
||||
|
||||
### ConfigProvider.config()
|
||||
|
||||
|
@ -6,7 +6,7 @@ import useMemo from 'rc-util/lib/hooks/useMemo';
|
||||
import { merge } from 'rc-util/lib/utils/set';
|
||||
import type { Options } from 'scroll-into-view-if-needed';
|
||||
|
||||
import warning from '../_util/warning';
|
||||
import warning, { WarningContext, type WarningContextProps } from '../_util/warning';
|
||||
import type { RequiredMark } from '../form/Form';
|
||||
import ValidateMessagesContext from '../form/validateMessagesContext';
|
||||
import type { InputProps } from '../input';
|
||||
@ -146,8 +146,7 @@ export interface ConfigProviderProps {
|
||||
popupOverflow?: PopupOverflow;
|
||||
theme?: ThemeConfig;
|
||||
|
||||
// TODO: wait for https://github.com/ant-design/ant-design/discussions/44551
|
||||
// warning?: WarningContextProps;
|
||||
warning?: WarningContextProps;
|
||||
|
||||
alert?: ComponentStyleConfig;
|
||||
anchor?: ComponentStyleConfig;
|
||||
@ -337,7 +336,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
colorPicker,
|
||||
datePicker,
|
||||
wave,
|
||||
// warning: warningConfig,
|
||||
warning: warningConfig,
|
||||
} = props;
|
||||
|
||||
// =================================== Context ===================================
|
||||
@ -427,7 +426,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
colorPicker,
|
||||
datePicker,
|
||||
wave,
|
||||
// warning: warningConfig,
|
||||
warning: warningConfig,
|
||||
};
|
||||
|
||||
const config = {
|
||||
@ -562,11 +561,11 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
}
|
||||
|
||||
// ================================== Warning ===================================
|
||||
// if (memoedConfig.warning) {
|
||||
// childNode = (
|
||||
// <WarningContext.Provider value={memoedConfig.warning}>{childNode}</WarningContext.Provider>
|
||||
// );
|
||||
// }
|
||||
if (memoedConfig.warning) {
|
||||
childNode = (
|
||||
<WarningContext.Provider value={memoedConfig.warning}>{childNode}</WarningContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
// =================================== Render ===================================
|
||||
if (componentDisabled !== undefined) {
|
||||
|
@ -14,8 +14,8 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*YC4ERpGAddoAAA
|
||||
ConfigProvider 使用 React 的 [context](https://facebook.github.io/react/docs/context.html) 特性,只需在应用外围包裹一次即可全局生效。
|
||||
|
||||
```tsx
|
||||
import { ConfigProvider } from 'antd';
|
||||
import React from 'react';
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
// ...
|
||||
const Demo: React.FC = () => (
|
||||
@ -46,7 +46,8 @@ export default Demo;
|
||||
<code src="./demo/theme.tsx">主题</code>
|
||||
<code src="./demo/wave.tsx">自定义波纹</code>
|
||||
<code src="./demo/prefixCls.tsx" debug>前缀</code>
|
||||
<code src="./demo/useConfig.tsx" debug>useConfig</code>
|
||||
<code src="./demo/useConfig.tsx" debug>获取配置</code>
|
||||
<code src="./demo/warning.tsx" debug>警告</code>
|
||||
|
||||
## API
|
||||
|
||||
@ -67,6 +68,7 @@ export default Demo;
|
||||
| renderEmpty | 自定义组件空状态。参考 [空状态](/components/empty-cn) | function(componentName: string): ReactNode | - | |
|
||||
| theme | 设置主题,参考 [定制主题](/docs/react/customize-theme-cn) | - | - | 5.0.0 |
|
||||
| virtual | 设置 `false` 时关闭虚拟滚动 | boolean | - | 4.3.0 |
|
||||
| warning | 设置警告等级,`strict` 为 `false` 时会将废弃相关信息聚合为单条信息 | { strict: boolean } | - | 5.10.0 |
|
||||
|
||||
### ConfigProvider.config()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user