mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 11:08:45 +08:00
refactor: CC => FC (#37886)
* fix: fix * fix: fix * fix: fix * fix: fix * fix: fix * fix: fix * fix: fix * fix: fix * fix: fix * test: fix test * fix: fix * fix: fix * fix: fix * test: add test * fix: fix test
This commit is contained in:
parent
77a75c37cd
commit
e084de38e8
@ -7,67 +7,58 @@ import defaultLocaleData from './default';
|
||||
export type LocaleComponentName = Exclude<keyof Locale, 'locale'>;
|
||||
|
||||
export interface LocaleReceiverProps<C extends LocaleComponentName = LocaleComponentName> {
|
||||
componentName: C;
|
||||
componentName?: C;
|
||||
defaultLocale?: Locale[C] | (() => Locale[C]);
|
||||
children: (
|
||||
locale: NonNullable<Locale[C]>,
|
||||
localeCode: string,
|
||||
fullLocale: Locale,
|
||||
) => React.ReactNode;
|
||||
) => React.ReactElement;
|
||||
}
|
||||
|
||||
export default class LocaleReceiver<
|
||||
C extends LocaleComponentName = LocaleComponentName,
|
||||
> extends React.Component<LocaleReceiverProps<C>> {
|
||||
static defaultProps = {
|
||||
componentName: 'global',
|
||||
};
|
||||
const LocaleReceiver = <C extends LocaleComponentName = LocaleComponentName>(
|
||||
props: LocaleReceiverProps<C>,
|
||||
) => {
|
||||
const { componentName = 'global' as C, defaultLocale, children } = props;
|
||||
const antLocale = React.useContext<LocaleContextProps | undefined>(LocaleContext);
|
||||
|
||||
static contextType = LocaleContext;
|
||||
|
||||
context: LocaleContextProps;
|
||||
|
||||
getLocale(): NonNullable<Locale[C]> {
|
||||
const { componentName, defaultLocale } = this.props;
|
||||
const locale = defaultLocale || defaultLocaleData[componentName ?? 'global'];
|
||||
const antLocale = this.context;
|
||||
const localeFromContext = componentName && antLocale ? antLocale[componentName] : {};
|
||||
const getLocale = React.useMemo<NonNullable<Locale[C]>>(() => {
|
||||
const locale = defaultLocale || defaultLocaleData[componentName];
|
||||
const localeFromContext = antLocale?.[componentName] ?? {};
|
||||
return {
|
||||
...(locale instanceof Function ? locale() : locale),
|
||||
...(localeFromContext || {}),
|
||||
};
|
||||
}
|
||||
}, [componentName, defaultLocale, antLocale]);
|
||||
|
||||
getLocaleCode() {
|
||||
const antLocale = this.context;
|
||||
const getLocaleCode = React.useMemo<string>(() => {
|
||||
const localeCode = antLocale && antLocale.locale;
|
||||
// Had use LocaleProvide but didn't set locale
|
||||
if (antLocale && antLocale.exist && !localeCode) {
|
||||
return defaultLocaleData.locale;
|
||||
}
|
||||
return localeCode;
|
||||
}
|
||||
return localeCode!;
|
||||
}, [antLocale]);
|
||||
|
||||
render() {
|
||||
return this.props.children(this.getLocale(), this.getLocaleCode(), this.context);
|
||||
}
|
||||
}
|
||||
return children(getLocale, getLocaleCode, antLocale!);
|
||||
};
|
||||
|
||||
export function useLocaleReceiver<T extends LocaleComponentName>(
|
||||
componentName: T,
|
||||
defaultLocale?: Locale[T] | Function,
|
||||
): [Locale[T]] {
|
||||
const antLocale = React.useContext(LocaleContext);
|
||||
export default LocaleReceiver;
|
||||
|
||||
const componentLocale = React.useMemo(() => {
|
||||
const locale = defaultLocale || defaultLocaleData[componentName || 'global'];
|
||||
const localeFromContext = componentName && antLocale ? antLocale[componentName] : {};
|
||||
export const useLocaleReceiver = <C extends LocaleComponentName = LocaleComponentName>(
|
||||
componentName: C,
|
||||
defaultLocale?: Locale[C] | (() => Locale[C]),
|
||||
): [Locale[C]] => {
|
||||
const antLocale = React.useContext<LocaleContextProps | undefined>(LocaleContext);
|
||||
|
||||
const getLocale = React.useMemo<NonNullable<Locale[C]>>(() => {
|
||||
const locale = defaultLocale || defaultLocaleData[componentName];
|
||||
const localeFromContext = antLocale?.[componentName] ?? {};
|
||||
return {
|
||||
...(typeof locale === 'function' ? (locale as Function)() : locale),
|
||||
...(typeof locale === 'function' ? locale() : locale),
|
||||
...(localeFromContext || {}),
|
||||
};
|
||||
}, [componentName, defaultLocale, antLocale]);
|
||||
|
||||
return [componentLocale];
|
||||
}
|
||||
return [getLocale];
|
||||
};
|
||||
|
@ -1,51 +1,38 @@
|
||||
import React, { memo, useContext, useRef, useState } from 'react';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
import LocaleProvider, { ANT_MARK } from '..';
|
||||
import React, { memo, useContext } from 'react';
|
||||
import { fireEvent, pureRender } from '../../../tests/utils';
|
||||
import LocaleProvider from '..';
|
||||
import LocaleContext from '../context';
|
||||
|
||||
const defaultLocale = { locale: 'locale' };
|
||||
// we use'memo' here in order to only render inner component while context changed.
|
||||
const CacheInner = memo(() => {
|
||||
const countRef = useRef(0);
|
||||
countRef.current++;
|
||||
// subscribe locale context
|
||||
useContext(LocaleContext);
|
||||
return (
|
||||
<div>
|
||||
Child Rendering Count: <span id="child_count">{countRef.current}</span>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
let innerCount = 0;
|
||||
let outerCount = 0;
|
||||
|
||||
const CacheOuter: React.FC = () => {
|
||||
// We use 'useState' here in order to trigger parent component rendering.
|
||||
const [count, setCount] = useState(1);
|
||||
const handleClick = () => {
|
||||
setCount(count + 1);
|
||||
};
|
||||
// During each rendering phase, the cached context value returned from method 'LocaleProvider#getMemoizedContextValue' will take effect.
|
||||
// So 'CacheInner' component won't rerender.
|
||||
return (
|
||||
<div>
|
||||
<button type="button" onClick={handleClick} id="parent_btn">
|
||||
Click
|
||||
</button>
|
||||
Parent Rendering Count: <span id="parent_count">{count}</span>
|
||||
<LocaleProvider locale={defaultLocale} _ANT_MARK__={ANT_MARK}>
|
||||
<CacheInner />
|
||||
</LocaleProvider>
|
||||
</div>
|
||||
);
|
||||
const handleClick = () => {
|
||||
outerCount++;
|
||||
};
|
||||
|
||||
it("Rendering on LocaleProvider won't trigger rendering on child component.", () => {
|
||||
const { container } = render(<CacheOuter />);
|
||||
fireEvent.click(container.querySelector('#parent_btn')!);
|
||||
expect(container.querySelector('#parent_count')?.innerHTML).toBe('2');
|
||||
// child component won't rerender
|
||||
expect(container.querySelector('#child_count')?.innerHTML).toBe('1');
|
||||
fireEvent.click(container.querySelector('#parent_btn')!);
|
||||
expect(container.querySelector('#parent_count')?.innerHTML).toBe('3');
|
||||
// child component won't rerender
|
||||
expect(container.querySelector('#child_count')?.innerHTML).toBe('1');
|
||||
// we use'memo' here in order to only render inner component while context changed.
|
||||
const CacheInner: React.FC = memo(() => {
|
||||
innerCount++;
|
||||
// subscribe locale context
|
||||
useContext(LocaleContext);
|
||||
return null;
|
||||
});
|
||||
|
||||
const CacheOuter: React.FC = memo(() => (
|
||||
<>
|
||||
<button type="button" onClick={handleClick} id="parent_btn">
|
||||
Click
|
||||
</button>
|
||||
<LocaleProvider locale={{ locale: 'locale' }}>
|
||||
<CacheInner />
|
||||
</LocaleProvider>
|
||||
</>
|
||||
));
|
||||
it("Rendering on LocaleProvider won't trigger rendering on child component.", () => {
|
||||
const { container } = pureRender(<CacheOuter />);
|
||||
expect(outerCount).toBe(0);
|
||||
expect(innerCount).toBe(1);
|
||||
fireEvent.click(container.querySelector('#parent_btn')!);
|
||||
expect(outerCount).toBe(1);
|
||||
expect(innerCount).toBe(1);
|
||||
});
|
||||
|
@ -1,23 +1,18 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { Modal } from '../..';
|
||||
import { sleep, render, fireEvent } from '../../../tests/utils';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import zhCN from '../zh_CN';
|
||||
|
||||
class Demo extends React.Component<{ type: string }> {
|
||||
static defaultProps = {};
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.type === 'dashboard') {
|
||||
const Demo: React.FC<{ type: string }> = ({ type }) => {
|
||||
useEffect(() => {
|
||||
if (type === 'dashboard') {
|
||||
Modal.confirm({ title: 'Hello World!' });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>{this.props.type}</div>;
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
return null;
|
||||
};
|
||||
|
||||
describe('Locale Provider demo', () => {
|
||||
it('change type', async () => {
|
||||
|
@ -191,7 +191,7 @@ const App: React.FC = () => (
|
||||
|
||||
describe('Locale Provider', () => {
|
||||
mountTest(() => (
|
||||
<LocaleProvider>
|
||||
<LocaleProvider locale={null as unknown as Locale}>
|
||||
<div />
|
||||
</LocaleProvider>
|
||||
));
|
||||
@ -237,7 +237,7 @@ describe('Locale Provider', () => {
|
||||
|
||||
it('set moment locale when locale changes', () => {
|
||||
const Test: React.FC<{ locale?: Locale }> = ({ locale }) => (
|
||||
<LocaleProvider locale={locale}>
|
||||
<LocaleProvider locale={locale!}>
|
||||
<div>
|
||||
<DatePicker defaultValue={moment()} open />
|
||||
</div>
|
||||
|
@ -1,8 +1,6 @@
|
||||
import memoizeOne from 'memoize-one';
|
||||
import type { ValidateMessages } from 'rc-field-form/lib/interface';
|
||||
import * as React from 'react';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
import type { PickerLocale as DatePickerLocale } from '../date-picker/generatePicker';
|
||||
import type { TransferLocale as TransferLocaleForEmpty } from '../empty';
|
||||
import type { ModalLocale } from '../modal/locale';
|
||||
@ -12,6 +10,7 @@ import type { PopconfirmLocale } from '../popconfirm/PurePanel';
|
||||
import type { TableLocale } from '../table/interface';
|
||||
import type { TransferLocale } from '../transfer';
|
||||
import type { UploadLocale } from '../upload/interface';
|
||||
import type { LocaleContextProps } from './context';
|
||||
import LocaleContext from './context';
|
||||
|
||||
export const ANT_MARK = 'internalMark';
|
||||
@ -54,45 +53,32 @@ export interface LocaleProviderProps {
|
||||
_ANT_MARK__?: string;
|
||||
}
|
||||
|
||||
export default class LocaleProvider extends React.Component<LocaleProviderProps, any> {
|
||||
static defaultProps = {
|
||||
locale: {},
|
||||
};
|
||||
|
||||
constructor(props: LocaleProviderProps) {
|
||||
super(props);
|
||||
changeConfirmLocale(props.locale && props.locale.Modal);
|
||||
const LocaleProvider: React.FC<LocaleProviderProps> = props => {
|
||||
const { locale = {} as Locale, children, _ANT_MARK__ } = props;
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warning(
|
||||
props._ANT_MARK__ === ANT_MARK,
|
||||
_ANT_MARK__ === ANT_MARK,
|
||||
'LocaleProvider',
|
||||
'`LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead: http://u.ant.design/locale',
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
changeConfirmLocale(this.props.locale && this.props.locale.Modal);
|
||||
}
|
||||
React.useEffect(() => {
|
||||
changeConfirmLocale(locale && locale.Modal);
|
||||
return () => {
|
||||
changeConfirmLocale();
|
||||
};
|
||||
}, [locale]);
|
||||
|
||||
componentDidUpdate(prevProps: LocaleProviderProps) {
|
||||
const { locale } = this.props;
|
||||
if (prevProps.locale !== locale) {
|
||||
changeConfirmLocale(locale && locale.Modal);
|
||||
}
|
||||
}
|
||||
const getMemoizedContextValue = React.useMemo<LocaleContextProps>(
|
||||
() => ({ ...locale, exist: true }),
|
||||
[locale],
|
||||
);
|
||||
|
||||
componentWillUnmount() {
|
||||
changeConfirmLocale();
|
||||
}
|
||||
return (
|
||||
<LocaleContext.Provider value={getMemoizedContextValue}>{children}</LocaleContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
getMemoizedContextValue = memoizeOne((localeValue: Locale): Locale & { exist?: boolean } => ({
|
||||
...localeValue,
|
||||
exist: true,
|
||||
}));
|
||||
|
||||
render() {
|
||||
const { locale, children } = this.props;
|
||||
const contextValue = this.getMemoizedContextValue(locale);
|
||||
return <LocaleContext.Provider value={contextValue}>{children}</LocaleContext.Provider>;
|
||||
}
|
||||
}
|
||||
export default LocaleProvider;
|
||||
|
Loading…
Reference in New Issue
Block a user