diff --git a/components/statistic/Countdown.tsx b/components/statistic/Countdown.tsx index 8870d37685..4803ef74d6 100644 --- a/components/statistic/Countdown.tsx +++ b/components/statistic/Countdown.tsx @@ -10,6 +10,11 @@ const REFRESH_INTERVAL = 1000 / 30; interface CountdownProps extends StatisticProps { value?: countdownValueType; format?: string; + onFinish?: () => void; +} + +function getTime(value?: countdownValueType) { + return interopDefault(moment)(value).valueOf(); } class Countdown extends React.Component { @@ -34,7 +39,7 @@ class Countdown extends React.Component { syncTimer = () => { const { value } = this.props; - const timestamp = interopDefault(moment)(value).valueOf(); + const timestamp = getTime(value); if (timestamp >= Date.now()) { this.startTimer(); } else { @@ -43,7 +48,7 @@ class Countdown extends React.Component { }; startTimer = () => { - if (this.countdownId !== undefined) return; + if (this.countdownId) return; this.countdownId = window.setInterval(() => { this.forceUpdate(); @@ -51,8 +56,16 @@ class Countdown extends React.Component { }; stopTimer = () => { - clearInterval(this.countdownId); - this.countdownId = undefined; + const { onFinish, value } = this.props; + if (this.countdownId) { + clearInterval(this.countdownId); + this.countdownId = undefined; + + const timestamp = getTime(value); + if (onFinish && timestamp < Date.now()) { + onFinish(); + } + } }; formatCountdown = (value: countdownValueType, config: FormatConfig) => { diff --git a/components/statistic/__tests__/index.test.js b/components/statistic/__tests__/index.test.js index bab5980ed8..05a2d76c96 100644 --- a/components/statistic/__tests__/index.test.js +++ b/components/statistic/__tests__/index.test.js @@ -61,17 +61,47 @@ describe('Statistic', () => { it('time going', async () => { const now = Date.now() + 1000; - const wrapper = mount(); + const onFinish = jest.fn(); + const wrapper = mount(); wrapper.update(); // setInterval should work const instance = wrapper.instance(); expect(instance.countdownId).not.toBe(undefined); - await delay(50); + await delay(10); wrapper.unmount(); expect(instance.countdownId).toBe(undefined); + expect(onFinish).not.toBeCalled(); + }); + + describe('time finished', () => { + it('not call if time already passed', () => { + const now = Date.now() - 1000; + + const onFinish = jest.fn(); + const wrapper = mount(); + wrapper.update(); + + const instance = wrapper.instance(); + expect(instance.countdownId).toBe(undefined); + expect(onFinish).not.toBeCalled(); + }); + + it('called if finished', async () => { + jest.useFakeTimers(); + const now = Date.now() + 10; + const onFinish = jest.fn(); + const wrapper = mount(); + wrapper.update(); + + MockDate.set(moment('2019-11-28 00:00:00')); + jest.runAllTimers(); + + expect(onFinish).toBeCalled(); + jest.useFakeTimers(); + }); }); }); }); diff --git a/components/statistic/demo/countdown.md b/components/statistic/demo/countdown.md index 0bfc1feb12..8fcf2ed571 100644 --- a/components/statistic/demo/countdown.md +++ b/components/statistic/demo/countdown.md @@ -19,10 +19,14 @@ import { Statistic, Row, Col } from 'antd'; const Countdown = Statistic.Countdown; const deadline = Date.now() + 1000 * 60 * 60 * 24 * 2 + 1000 * 30; // Moment is also OK +function onFinish() { + console.log('finished!'); +} + ReactDOM.render( - + diff --git a/components/statistic/index.en-US.md b/components/statistic/index.en-US.md index a9dffd9a74..28b7da33e6 100644 --- a/components/statistic/index.en-US.md +++ b/components/statistic/index.en-US.md @@ -32,6 +32,7 @@ Display statistic number. | Property | Description | Type | Default | | -------- | ----------- | ---- | ------- | | format | Format as [moment](http://momentjs.com/) | string | 'HH:mm:ss' | +| onFinish | Trigger when time's up | () => void | - | | prefix | prefix node of value | string \| ReactNode | - | | suffix | suffix node of value | string \| ReactNode | - | | title | Display title | string \| ReactNode | - | diff --git a/components/statistic/index.zh-CN.md b/components/statistic/index.zh-CN.md index 186dba7e83..7ac9b78850 100644 --- a/components/statistic/index.zh-CN.md +++ b/components/statistic/index.zh-CN.md @@ -33,6 +33,7 @@ title: Statistic | 参数 | 说明 | 类型 | 默认值 | | -------- | ----------- | ---- | ------- | | format | 格式化倒计时展示,参考 [moment](http://momentjs.com/) | string | 'HH:mm:ss' | +| onFinish | 倒计时完成时触发 | () => void | - | | prefix | 设置数值的前缀 | string \| ReactNode | - | | suffix | 设置数值的后缀 | string \| ReactNode | - | | title | 数值的标题 | string \| ReactNode | - |