mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
refactor: CC => FC (#37938)
* fix: f * refactor: CC => FC * fix: add ignore * fix: fix * fix: fix * fix: remove onChange * fix: remove onFinish * fix: remove onFinish * fix: remove useCallback * fix: eslint error
This commit is contained in:
parent
c04bdd0928
commit
7b285ea4c1
@ -1,8 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import useForceUpdate from '../_util/hooks/useForceUpdate';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
import type { StatisticProps } from './Statistic';
|
||||
import Statistic from './Statistic';
|
||||
import type { countdownValueType, FormatConfig } from './utils';
|
||||
import type { countdownValueType, FormatConfig, valueType } from './utils';
|
||||
import { formatCountdown } from './utils';
|
||||
|
||||
const REFRESH_INTERVAL = 1000 / 30;
|
||||
@ -15,84 +16,54 @@ interface CountdownProps extends StatisticProps {
|
||||
}
|
||||
|
||||
function getTime(value?: countdownValueType) {
|
||||
return new Date(value as any).getTime();
|
||||
return new Date(value as valueType).getTime();
|
||||
}
|
||||
|
||||
class Countdown extends React.Component<CountdownProps, {}> {
|
||||
static defaultProps: Partial<CountdownProps> = {
|
||||
format: 'HH:mm:ss',
|
||||
const Countdown: React.FC<CountdownProps> = props => {
|
||||
const { value, format = 'HH:mm:ss', onChange, onFinish } = props;
|
||||
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
const countdown = React.useRef<NodeJS.Timer | null>(null);
|
||||
|
||||
const stopTimer = () => {
|
||||
onFinish?.();
|
||||
if (countdown.current) {
|
||||
clearInterval(countdown.current);
|
||||
countdown.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
countdownId?: number;
|
||||
|
||||
componentDidMount() {
|
||||
this.syncTimer();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.syncTimer();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.stopTimer();
|
||||
}
|
||||
|
||||
syncTimer = () => {
|
||||
const { value } = this.props;
|
||||
|
||||
const syncTimer = () => {
|
||||
const timestamp = getTime(value);
|
||||
if (timestamp >= Date.now()) {
|
||||
this.startTimer();
|
||||
} else {
|
||||
this.stopTimer();
|
||||
countdown.current = setInterval(() => {
|
||||
forceUpdate();
|
||||
onChange?.(timestamp - Date.now());
|
||||
if (timestamp < Date.now()) {
|
||||
stopTimer();
|
||||
}
|
||||
}, REFRESH_INTERVAL);
|
||||
}
|
||||
};
|
||||
|
||||
startTimer = () => {
|
||||
if (this.countdownId) return;
|
||||
|
||||
const { onChange, value } = this.props;
|
||||
const timestamp = getTime(value);
|
||||
|
||||
this.countdownId = window.setInterval(() => {
|
||||
this.forceUpdate();
|
||||
|
||||
if (onChange && timestamp > Date.now()) {
|
||||
onChange(timestamp - Date.now());
|
||||
React.useEffect(() => {
|
||||
syncTimer();
|
||||
return () => {
|
||||
if (countdown.current) {
|
||||
clearInterval(countdown.current);
|
||||
countdown.current = null;
|
||||
}
|
||||
}, REFRESH_INTERVAL);
|
||||
};
|
||||
};
|
||||
}, [value]);
|
||||
|
||||
stopTimer = () => {
|
||||
const { onFinish, value } = this.props;
|
||||
if (this.countdownId) {
|
||||
clearInterval(this.countdownId);
|
||||
this.countdownId = undefined;
|
||||
const formatter = (formatValue: countdownValueType, config: FormatConfig) =>
|
||||
formatCountdown(formatValue, { ...config, format });
|
||||
|
||||
const timestamp = getTime(value);
|
||||
if (onFinish && timestamp < Date.now()) {
|
||||
onFinish();
|
||||
}
|
||||
}
|
||||
};
|
||||
const valueRender = (node: React.ReactElement<HTMLDivElement>) =>
|
||||
cloneElement(node, { title: undefined });
|
||||
|
||||
formatCountdown = (value: countdownValueType, config: FormatConfig) => {
|
||||
const { format } = this.props;
|
||||
return formatCountdown(value, { ...config, format });
|
||||
};
|
||||
return <Statistic {...props} valueRender={valueRender} formatter={formatter} />;
|
||||
};
|
||||
|
||||
// Countdown do not need display the timestamp
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
valueRender = (node: React.ReactElement<HTMLDivElement>) =>
|
||||
cloneElement(node, {
|
||||
title: undefined,
|
||||
});
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Statistic valueRender={this.valueRender} {...this.props} formatter={this.formatCountdown} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Countdown;
|
||||
export default React.memo(Countdown);
|
||||
|
@ -5,7 +5,6 @@ import Statistic from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, render, sleep } from '../../../tests/utils';
|
||||
import type Countdown from '../Countdown';
|
||||
import { formatTimeStr } from '../utils';
|
||||
|
||||
describe('Statistic', () => {
|
||||
@ -100,13 +99,8 @@ describe('Statistic', () => {
|
||||
it('time going', async () => {
|
||||
const now = Date.now() + 1000;
|
||||
const onFinish = jest.fn();
|
||||
const instance = React.createRef<Countdown>();
|
||||
const { unmount } = render(
|
||||
<Statistic.Countdown ref={instance} value={now} onFinish={onFinish} />,
|
||||
);
|
||||
|
||||
// setInterval should work
|
||||
expect(instance.current!.countdownId).not.toBe(undefined);
|
||||
const { unmount } = render(<Statistic.Countdown value={now} onFinish={onFinish} />);
|
||||
|
||||
await sleep(10);
|
||||
|
||||
@ -156,11 +150,9 @@ describe('Statistic', () => {
|
||||
describe('time finished', () => {
|
||||
it('not call if time already passed', () => {
|
||||
const now = Date.now() - 1000;
|
||||
const instance = React.createRef<Countdown>();
|
||||
const onFinish = jest.fn();
|
||||
render(<Statistic.Countdown ref={instance} value={now} onFinish={onFinish} />);
|
||||
render(<Statistic.Countdown value={now} onFinish={onFinish} />);
|
||||
|
||||
expect(instance.current!.countdownId).toBe(undefined);
|
||||
expect(onFinish).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user