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:
lijianan 2022-10-11 22:35:50 +08:00 committed by GitHub
parent c04bdd0928
commit 7b285ea4c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 78 deletions

View File

@ -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);

View File

@ -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();
});