mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-02 03:59:01 +08:00
chore: Static warning if exist theme in CP (#41157)
* chore: warning for dynamic theme * chore: warning for static context * chore: add ignore
This commit is contained in:
parent
1df1034f20
commit
36f44575c8
@ -27,6 +27,24 @@ import type { SizeType } from './SizeContext';
|
||||
import SizeContext, { SizeContextProvider } from './SizeContext';
|
||||
import useStyle from './style';
|
||||
|
||||
/**
|
||||
* Since too many feedback using static method like `Modal.confirm` not getting theme,
|
||||
* we record the theme register info here to help developer get warning info.
|
||||
*/
|
||||
let existThemeConfig = false;
|
||||
|
||||
export const warnContext: (componentName: string) => void =
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? (componentName: string) => {
|
||||
warning(
|
||||
!existThemeConfig,
|
||||
componentName,
|
||||
`Static function can not consume context like dynamic theme. Please use 'App' component instead.`,
|
||||
);
|
||||
}
|
||||
: /* istanbul ignore next */
|
||||
null!;
|
||||
|
||||
export {
|
||||
type RenderEmptyHandler,
|
||||
ConfigContext,
|
||||
@ -192,6 +210,10 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
|
||||
|
||||
const mergedTheme = useTheme(theme, parentContext.theme);
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
existThemeConfig = existThemeConfig || !!mergedTheme;
|
||||
}
|
||||
|
||||
const baseConfig = {
|
||||
csp,
|
||||
autoInsertSpaceInButton,
|
||||
|
57
components/message/__tests__/static-warning.test.tsx
Normal file
57
components/message/__tests__/static-warning.test.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import message, { actWrapper } from '..';
|
||||
import { act, render, waitFakeTimer } from '../../../tests/utils';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import { awaitPromise, triggerMotionEnd } from './util';
|
||||
|
||||
describe('message static warning', () => {
|
||||
beforeAll(() => {
|
||||
actWrapper(act);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// Clean up
|
||||
message.destroy();
|
||||
await triggerMotionEnd();
|
||||
|
||||
jest.useRealTimers();
|
||||
|
||||
await awaitPromise();
|
||||
});
|
||||
|
||||
// Follow test need keep order
|
||||
it('no warning', async () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
message.success({
|
||||
content: <div className="bamboo" />,
|
||||
duration: 0,
|
||||
});
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(document.querySelector('.bamboo')).toBeTruthy();
|
||||
|
||||
expect(errSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('warning if use theme', async () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
render(<ConfigProvider theme={{}} />);
|
||||
|
||||
message.success({
|
||||
content: <div className="light" />,
|
||||
duration: 0,
|
||||
});
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(document.querySelector('.light')).toBeTruthy();
|
||||
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
"Warning: [antd: message] Static function can not consume context like dynamic theme. Please use 'App' component instead.",
|
||||
);
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import { render } from 'rc-util/lib/React/render';
|
||||
import * as React from 'react';
|
||||
import ConfigProvider, { globalConfig } from '../config-provider';
|
||||
import ConfigProvider, { globalConfig, warnContext } from '../config-provider';
|
||||
import type {
|
||||
ArgsProps,
|
||||
ConfigOptions,
|
||||
@ -262,6 +262,11 @@ function open(config: ArgsProps): MessageType {
|
||||
}
|
||||
|
||||
function typeOpen(type: NoticeType, args: Parameters<TypeOpen>): MessageType {
|
||||
// Warning if exist theme
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warnContext('message');
|
||||
}
|
||||
|
||||
const result = wrapPromiseFn((resolve) => {
|
||||
let closeFn: VoidFunction;
|
||||
|
||||
|
49
components/modal/__tests__/static-warning.test.tsx
Normal file
49
components/modal/__tests__/static-warning.test.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import * as React from 'react';
|
||||
import Modal from '..';
|
||||
import { render, waitFakeTimer } from '../../../tests/utils';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import { resetWarned } from '../../_util/warning';
|
||||
|
||||
describe('Modal.confirm warning', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
resetWarned();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
Modal.destroyAll();
|
||||
|
||||
await waitFakeTimer();
|
||||
document.body.innerHTML = '';
|
||||
jest.clearAllTimers();
|
||||
});
|
||||
|
||||
// Follow test need keep order
|
||||
it('no warning', async () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
Modal.confirm({
|
||||
content: <div className="bamboo" />,
|
||||
});
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(document.querySelector('.bamboo')).toBeTruthy();
|
||||
|
||||
expect(errSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('warning if use theme', async () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
render(<ConfigProvider theme={{}} />);
|
||||
|
||||
Modal.confirm({
|
||||
content: <div className="light" />,
|
||||
});
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(document.querySelector('.light')).toBeTruthy();
|
||||
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
"Warning: [antd: Modal] Static function can not consume context like dynamic theme. Please use 'App' component instead.",
|
||||
);
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import { render as reactRender, unmount as reactUnmount } from 'rc-util/lib/React/render';
|
||||
import * as React from 'react';
|
||||
import { globalConfig } from '../config-provider';
|
||||
import { globalConfig, warnContext } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import ConfirmDialog from './ConfirmDialog';
|
||||
import destroyFns from './destroyFns';
|
||||
@ -23,6 +23,11 @@ export type ModalFunc = (props: ModalFuncProps) => {
|
||||
export type ModalStaticFunctions = Record<NonNullable<ModalFuncProps['type']>, ModalFunc>;
|
||||
|
||||
export default function confirm(config: ModalFuncProps) {
|
||||
// Warning if exist theme
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warnContext('Modal');
|
||||
}
|
||||
|
||||
const container = document.createDocumentFragment();
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
let currentConfig = { ...config, close, open: true } as any;
|
||||
|
57
components/notification/__tests__/static-warning.test.tsx
Normal file
57
components/notification/__tests__/static-warning.test.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import notification, { actWrapper } from '..';
|
||||
import { act, render, waitFakeTimer } from '../../../tests/utils';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import { awaitPromise, triggerMotionEnd } from './util';
|
||||
|
||||
describe('notification static warning', () => {
|
||||
beforeAll(() => {
|
||||
actWrapper(act);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// Clean up
|
||||
notification.destroy();
|
||||
await triggerMotionEnd();
|
||||
|
||||
jest.useRealTimers();
|
||||
|
||||
await awaitPromise();
|
||||
});
|
||||
|
||||
// Follow test need keep order
|
||||
it('no warning', async () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
notification.open({
|
||||
message: <div className="bamboo" />,
|
||||
duration: 0,
|
||||
});
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(document.querySelector('.bamboo')).toBeTruthy();
|
||||
|
||||
expect(errSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('warning if use theme', async () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
render(<ConfigProvider theme={{}} />);
|
||||
|
||||
notification.open({
|
||||
message: <div className="light" />,
|
||||
duration: 0,
|
||||
});
|
||||
await waitFakeTimer();
|
||||
|
||||
expect(document.querySelector('.light')).toBeTruthy();
|
||||
|
||||
expect(errSpy).toHaveBeenCalledWith(
|
||||
"Warning: [antd: notification] Static function can not consume context like dynamic theme. Please use 'App' component instead.",
|
||||
);
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import { render } from 'rc-util/lib/React/render';
|
||||
import * as React from 'react';
|
||||
import ConfigProvider, { globalConfig } from '../config-provider';
|
||||
import ConfigProvider, { globalConfig, warnContext } from '../config-provider';
|
||||
import type { ArgsProps, GlobalConfigProps, NotificationInstance } from './interface';
|
||||
import PurePanel from './PurePanel';
|
||||
import useNotification, { useInternalNotification } from './useNotification';
|
||||
@ -201,6 +201,11 @@ function setNotificationGlobalConfig(config: GlobalConfigProps) {
|
||||
}
|
||||
|
||||
function open(config: ArgsProps) {
|
||||
// Warning if exist theme
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warnContext('notification');
|
||||
}
|
||||
|
||||
taskQueue.push({
|
||||
type: 'open',
|
||||
config,
|
||||
|
Loading…
Reference in New Issue
Block a user