Repository: alibaba/hooks
Pull request #745 (2020-11-23 14:05:51)

optimize:useCountdown
### 定时器结束后，触发回调执行
> 使用场景：在项目中，需要启动一个定时器来进行倒计时。时间结束，刷新该页面重新发送请求


Patch:
diff --git a/packages/hooks/src/useCountDown/demo/demo2.tsx b/packages/hooks/src/useCountDown/demo/demo2.tsx
index dda707df..dfe5bc54 100644
--- a/packages/hooks/src/useCountDown/demo/demo2.tsx
+++ b/packages/hooks/src/useCountDown/demo/demo2.tsx
@@ -3,14 +3,18 @@
  * desc: Controll countdown and interval status manually
  *
  * title.zh-CN: 进阶使用
- * desc.zh-CN: 手动启用并控制计时器状态, 适用于验证码或类似场景
+ * desc.zh-CN: 手动启用并控制计时器状态, 适用于验证码或类似场景; 时间结束后触发onEnd回调
  */
 
 import React from 'react';
 import useCountDown from '../index';
 
 export default () => {
-  const [countdown, setTargetDate] = useCountDown();
+  const onEnd = () => {
+    alert('End of the time');
+    console.log('onEnd of the time');
+  };
+  const [countdown, setTargetDate] = useCountDown({ onEnd: onEnd });
 
   return (
     <>
diff --git a/packages/hooks/src/useCountDown/index.en-US.md b/packages/hooks/src/useCountDown/index.en-US.md
index 1972a074..491814af 100644
--- a/packages/hooks/src/useCountDown/index.en-US.md
+++ b/packages/hooks/src/useCountDown/index.en-US.md
@@ -27,6 +27,7 @@ const [countdown, setTargetDate, formattedRes] = useCountDown(
   {
     targetDate,
     interval,
+    onEnd
   }
 );
 ```
@@ -54,6 +55,7 @@ If you only need to be accurate to the second, you can use it like this `Math.ro
 | --------- | -------------------- | ------------------------------------------------------- | ----------- |
 | targetDate   | Future time        | `TDate`                                                 | `undefined` |
 | interval  | Change time interval (ms)        | `number`                                                | `1000`      |
+| onEnd |  The callback function after the end of the future time  |`Function`                                           |`undefined`|
 
 ### Return
 
diff --git a/packages/hooks/src/useCountDown/index.ts b/packages/hooks/src/useCountDown/index.ts
index 899352f1..68558561 100644
--- a/packages/hooks/src/useCountDown/index.ts
+++ b/packages/hooks/src/useCountDown/index.ts
@@ -1,11 +1,13 @@
 import { useEffect, useMemo, useState } from 'react';
 import dayjs from 'dayjs';
+import usePersistFn from '../usePersistFn';
 
 export type TDate = Date | number | string | undefined;
 
 export type Options = {
   targetDate?: TDate;
   interval?: number;
+  onEnd?: () => void;
 };
 
 export interface FormattedRes {
@@ -39,11 +41,17 @@ const parseMs = (milliseconds: number): FormattedRes => {
 };
 
 const useCountdown = (options?: Options) => {
-  const { targetDate, interval = 1000 } = options || {};
+  const { targetDate, interval = 1000, onEnd } = options || {};
 
   const [target, setTargetDate] = useState<TDate>(targetDate);
   const [timeLeft, setTimeLeft] = useState(() => calcLeft(target));
 
+  const onEndPersistFn = usePersistFn(() => {
+    if (onEnd) {
+      onEnd();
+    }
+  });
+
   useEffect(() => {
     if (!target) {
       // for stop
@@ -59,6 +67,7 @@ const useCountdown = (options?: Options) => {
       setTimeLeft(targetLeft);
       if (targetLeft === 0) {
         clearInterval(timer);
+          onEndPersistFn();
       }
     }, interval);
 
diff --git a/packages/hooks/src/useCountDown/index.zh-CN.md b/packages/hooks/src/useCountDown/index.zh-CN.md
index e3401b78..dfec18a9 100644
--- a/packages/hooks/src/useCountDown/index.zh-CN.md
+++ b/packages/hooks/src/useCountDown/index.zh-CN.md
@@ -36,6 +36,7 @@ const [countdown, setTargetDate, formattedRes] = useCountDown(
   {
     targetDate,
     interval,
+    onEnd
   }
 );
 ```
@@ -54,6 +55,7 @@ const [countdown, setTargetDate, formattedRes] = useCountDown(
 | --------- | -------------- | ------------------------------------------------------- | ----------- |
 | targetDate   | 未来时间     | `TDate`                                                 | `undefined` |
 | interval  | 变化时间间隔（毫秒）     | `number`                                                | `1000`      |
+| onEnd |  未来时间结束后的回调函数  |`Function`                                           |`undefined`|
 
 
 ### Result


Test patch:
diff --git a/packages/hooks/src/useCountDown/__tests__/index.test.ts b/packages/hooks/src/useCountDown/__tests__/index.test.ts
index 21b118c3..1a01babe 100644
--- a/packages/hooks/src/useCountDown/__tests__/index.test.ts
+++ b/packages/hooks/src/useCountDown/__tests__/index.test.ts
@@ -4,11 +4,12 @@ import useCountDown, { TDate, Options } from '../index';
 // https://github.com/facebook/jest/issues/2234
 jest.spyOn(Date, 'now').mockImplementation(() => 1479427200000);
 
-const init = (_targetDate?: TDate, _interval?: Options['interval']) =>
-  renderHook(({ targetDate, interval }) => useCountDown({ targetDate, interval }), {
+const init = (_targetDate?: TDate, _interval?: Options['interval'], onEnd?: Options['onEnd']) =>
+  renderHook(({ targetDate, interval }) => useCountDown({ targetDate, interval, onEnd }), {
     initialProps: {
       targetDate: _targetDate,
       interval: _interval,
+      onEnd,
     },
   });
 
@@ -96,4 +97,14 @@ describe('useCountDown Hooks', () => {
     expect(result.current[0]).toBeLessThanOrEqual(0);
     expect(result.current[2].seconds).toEqual(0);
   });
+
+  it('it onEnd should work', async () => {
+    let count = 0;
+    const onEnd = () => {
+      count++;
+    };
+    init(Date.now() + 5000, 1000, onEnd);
+    jest.advanceTimersByTime(6000);
+    expect(count).toEqual(1);
+  });
 });