mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-05 05:28:20 +08:00
commit
442ad961ee
@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import { render } from '@testing-library/react';
|
||||
import debounce from 'lodash/debounce';
|
||||
import Spin from '..';
|
||||
@ -32,7 +31,7 @@ describe('delay spinning', () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('should cancel debounce function when unmount', async () => {
|
||||
it('should cancel debounce function when unmount', () => {
|
||||
const debouncedFn = jest.fn();
|
||||
const cancel = jest.fn();
|
||||
(debouncedFn as any).cancel = cancel;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
// eslint-disable-next-line import/no-named-as-default
|
||||
import { render } from '@testing-library/react';
|
||||
import { waitFakeTimer } from '../../../tests/utils';
|
||||
import Spin from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
@ -15,10 +15,8 @@ describe('Spin', () => {
|
||||
<div>content</div>
|
||||
</Spin>,
|
||||
);
|
||||
expect((container.querySelector('.ant-spin-nested-loading')! as HTMLElement).style.length).toBe(
|
||||
0,
|
||||
);
|
||||
expect((container.querySelector('.ant-spin')! as HTMLElement).style.background).toBe('red');
|
||||
expect(container.querySelector<HTMLElement>('.ant-spin-nested-loading')?.style.length).toBe(0);
|
||||
expect(container.querySelector<HTMLElement>('.ant-spin')?.style.background).toBe('red');
|
||||
});
|
||||
|
||||
it("should render custom indicator when it's set", () => {
|
||||
@ -27,11 +25,15 @@ describe('Spin', () => {
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should be controlled by spinning', () => {
|
||||
it('should be controlled by spinning', async () => {
|
||||
jest.useFakeTimers();
|
||||
const { container, rerender } = render(<Spin spinning={false} />);
|
||||
expect(container.querySelector('.ant-spin-spinning')).toBeFalsy();
|
||||
rerender(<Spin spinning />);
|
||||
await waitFakeTimer();
|
||||
expect(container.querySelector('.ant-spin-spinning')).toBeTruthy();
|
||||
jest.clearAllTimers();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('if indicator set null should not be render default indicator', () => {
|
||||
|
@ -35,11 +35,6 @@ export type SpinFCType = React.FC<SpinProps> & {
|
||||
setDefaultIndicator: (indicator: React.ReactNode) => void;
|
||||
};
|
||||
|
||||
export interface SpinState {
|
||||
spinning?: boolean;
|
||||
notCssAnimationSupported?: boolean;
|
||||
}
|
||||
|
||||
// Render indicator
|
||||
let defaultIndicator: React.ReactNode = null;
|
||||
|
||||
@ -59,8 +54,8 @@ function renderIndicator(prefixCls: string, props: SpinClassProps): React.ReactN
|
||||
}
|
||||
|
||||
if (isValidElement(defaultIndicator)) {
|
||||
return cloneElement(defaultIndicator as SpinIndicator, {
|
||||
className: classNames((defaultIndicator as SpinIndicator).props.className, dotClassName),
|
||||
return cloneElement(defaultIndicator, {
|
||||
className: classNames(defaultIndicator.props.className, dotClassName),
|
||||
});
|
||||
}
|
||||
|
||||
@ -78,80 +73,38 @@ function shouldDelay(spinning?: boolean, delay?: number): boolean {
|
||||
return !!spinning && !!delay && !isNaN(Number(delay));
|
||||
}
|
||||
|
||||
class Spin extends React.Component<SpinClassProps, SpinState> {
|
||||
static defaultProps = {
|
||||
spinning: true,
|
||||
size: 'default' as SpinSize,
|
||||
wrapperClassName: '',
|
||||
};
|
||||
const Spin: React.FC<SpinClassProps> = props => {
|
||||
const {
|
||||
spinPrefixCls: prefixCls,
|
||||
spinning: customSpinning = true,
|
||||
delay,
|
||||
className,
|
||||
size = 'default',
|
||||
tip,
|
||||
wrapperClassName,
|
||||
style,
|
||||
children,
|
||||
hashId,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
originalUpdateSpinning: () => void;
|
||||
const [spinning, setSpinning] = React.useState<boolean>(
|
||||
() => customSpinning && !shouldDelay(customSpinning, delay),
|
||||
);
|
||||
|
||||
constructor(props: SpinClassProps) {
|
||||
super(props);
|
||||
|
||||
const { spinning, delay } = props;
|
||||
const shouldBeDelayed = shouldDelay(spinning, delay);
|
||||
this.state = {
|
||||
spinning: spinning && !shouldBeDelayed,
|
||||
React.useEffect(() => {
|
||||
const updateSpinning = debounce<() => void>(() => {
|
||||
setSpinning(customSpinning);
|
||||
}, delay);
|
||||
updateSpinning();
|
||||
return () => {
|
||||
updateSpinning?.cancel?.();
|
||||
};
|
||||
this.originalUpdateSpinning = this.updateSpinning;
|
||||
this.debouncifyUpdateSpinning(props);
|
||||
}
|
||||
}, [delay, customSpinning]);
|
||||
|
||||
componentDidMount() {
|
||||
this.updateSpinning();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.debouncifyUpdateSpinning();
|
||||
this.updateSpinning();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.cancelExistingSpin();
|
||||
}
|
||||
|
||||
debouncifyUpdateSpinning = (props?: SpinClassProps) => {
|
||||
const { delay } = props || this.props;
|
||||
if (delay) {
|
||||
this.cancelExistingSpin();
|
||||
this.updateSpinning = debounce(this.originalUpdateSpinning, delay);
|
||||
}
|
||||
};
|
||||
|
||||
updateSpinning = () => {
|
||||
const { spinning } = this.props;
|
||||
const { spinning: currentSpinning } = this.state;
|
||||
if (currentSpinning !== spinning) {
|
||||
this.setState({ spinning });
|
||||
}
|
||||
};
|
||||
|
||||
cancelExistingSpin() {
|
||||
const { updateSpinning } = this;
|
||||
if (updateSpinning && (updateSpinning as any).cancel) {
|
||||
(updateSpinning as any).cancel();
|
||||
}
|
||||
}
|
||||
|
||||
isNestedPattern() {
|
||||
return !!(this.props && typeof this.props.children !== 'undefined');
|
||||
}
|
||||
|
||||
renderSpin = ({ direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
spinPrefixCls: prefixCls,
|
||||
hashId,
|
||||
className,
|
||||
size,
|
||||
tip,
|
||||
wrapperClassName,
|
||||
style,
|
||||
...restProps
|
||||
} = this.props;
|
||||
const { spinning } = this.state;
|
||||
const isNestedPattern = () => typeof children !== 'undefined';
|
||||
|
||||
const renderSpin = ({ direction }: ConfigConsumerProps) => {
|
||||
const spinClassName = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
@ -166,7 +119,7 @@ class Spin extends React.Component<SpinClassProps, SpinState> {
|
||||
);
|
||||
|
||||
// fix https://fb.me/react-unknown-prop
|
||||
const divProps = omit(restProps, ['spinning', 'delay', 'indicator', 'prefixCls']);
|
||||
const divProps = omit(restProps, ['indicator', 'prefixCls']);
|
||||
|
||||
const spinElement = (
|
||||
<div
|
||||
@ -176,11 +129,12 @@ class Spin extends React.Component<SpinClassProps, SpinState> {
|
||||
aria-live="polite"
|
||||
aria-busy={spinning}
|
||||
>
|
||||
{renderIndicator(prefixCls, this.props)}
|
||||
{renderIndicator(prefixCls, props)}
|
||||
{tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null}
|
||||
</div>
|
||||
);
|
||||
if (this.isNestedPattern()) {
|
||||
|
||||
if (isNestedPattern()) {
|
||||
const containerClassName = classNames(`${prefixCls}-container`, {
|
||||
[`${prefixCls}-blur`]: spinning,
|
||||
});
|
||||
@ -191,18 +145,15 @@ class Spin extends React.Component<SpinClassProps, SpinState> {
|
||||
>
|
||||
{spinning && <div key="loading">{spinElement}</div>}
|
||||
<div className={containerClassName} key="container">
|
||||
{this.props.children}
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return spinElement;
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderSpin}</ConfigConsumer>;
|
||||
}
|
||||
}
|
||||
return <ConfigConsumer>{renderSpin}</ConfigConsumer>;
|
||||
};
|
||||
|
||||
const SpinFC: SpinFCType = props => {
|
||||
const { prefixCls: customizePrefixCls } = props;
|
||||
|
@ -64,7 +64,7 @@ const App: React.FC = () => {
|
||||
};
|
||||
|
||||
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
|
||||
console.log('selectedRowKeys changed: ', selectedRowKeys);
|
||||
console.log('selectedRowKeys changed: ', newSelectedRowKeys);
|
||||
setSelectedRowKeys(newSelectedRowKeys);
|
||||
};
|
||||
|
||||
|
@ -55,7 +55,7 @@ const App: React.FC = () => {
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
|
||||
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
|
||||
console.log('selectedRowKeys changed: ', selectedRowKeys);
|
||||
console.log('selectedRowKeys changed: ', newSelectedRowKeys);
|
||||
setSelectedRowKeys(newSelectedRowKeys);
|
||||
};
|
||||
|
||||
|
@ -14,4 +14,4 @@ services:
|
||||
- './jest-puppeteer.config.js:/app/jest-puppeteer.config.js'
|
||||
- './imageSnapshots:/app/imageSnapshots'
|
||||
- './imageDiffSnapshots:/app/imageDiffSnapshots'
|
||||
entrypoint: "jest --config .jest.image.js --no-cache -i"
|
||||
entrypoint: "npm run test-image:docker"
|
||||
|
@ -92,6 +92,7 @@
|
||||
"tsc": "tsc --noEmit",
|
||||
"site:test": "jest --config .jest.site.js --cache=false --force-exit",
|
||||
"test-image": "npm run dist && docker-compose run tests",
|
||||
"test-image:docker": "node node_modules/puppeteer/install.js && jest --config .jest.image.js --no-cache -i",
|
||||
"argos": "node ./scripts/argos-upload.js",
|
||||
"version": "node ./scripts/generate-version",
|
||||
"install-react-16": "npm i --no-save --legacy-peer-deps react@16 react-dom@16",
|
||||
|
Loading…
Reference in New Issue
Block a user