From 120099c7019a88938d8d52a5d4f8f3db39111e20 Mon Sep 17 00:00:00 2001 From: joe-leong <39672163+joe-leong@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:04:23 +0800 Subject: [PATCH] fix(useCountDown): targetDate resets leftTime (#2346) --- .../src/useCountDown/__tests__/index.test.ts | 29 ++++++++++++++++++- packages/hooks/src/useCountDown/index.ts | 12 ++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/packages/hooks/src/useCountDown/__tests__/index.test.ts b/packages/hooks/src/useCountDown/__tests__/index.test.ts index 57b527bdef..5a8365d37a 100644 --- a/packages/hooks/src/useCountDown/__tests__/index.test.ts +++ b/packages/hooks/src/useCountDown/__tests__/index.test.ts @@ -1,5 +1,6 @@ import { act, renderHook } from '@testing-library/react'; -import useCountDown, { Options } from '../index'; +import type { Options } from '../index'; +import useCountDown from '../index'; const setup = (options: Options = {}) => renderHook((props: Options = options) => useCountDown(props)); @@ -235,4 +236,30 @@ describe('useCountDown', () => { const { result } = setup({ leftTime: -5 * 1000 }); expect(result.current[0]).toBe(0); }); + + it('run with timeLeft should not be reset after targetDate changed', async () => { + let targetDate = Date.now() + 8000; + + const { result, rerender } = setup({ + leftTime: 6000, + targetDate, + }); + expect(result.current[0]).toBe(6000); + + act(() => { + jest.advanceTimersByTime(2000); + }); + rerender({ + leftTime: 6000, + targetDate: targetDate, + }); + expect(result.current[0]).toBe(4000); + + targetDate = Date.now() + 9000; + rerender({ + leftTime: 6000, + targetDate: targetDate, + }); + expect(result.current[0]).toBe(4000); + }); }); diff --git a/packages/hooks/src/useCountDown/index.ts b/packages/hooks/src/useCountDown/index.ts index 6f64a9711f..bcb8866b76 100644 --- a/packages/hooks/src/useCountDown/index.ts +++ b/packages/hooks/src/useCountDown/index.ts @@ -42,13 +42,11 @@ const parseMs = (milliseconds: number): FormattedRes => { const useCountdown = (options: Options = {}) => { const { leftTime, targetDate, interval = 1000, onEnd } = options || {}; - const target = useMemo(() => { - if ('leftTime' in options) { - return isNumber(leftTime) && leftTime > 0 ? Date.now() + leftTime : undefined; - } else { - return targetDate; - } - }, [leftTime, targetDate]); + const memoLeftTime = useMemo(() => { + return isNumber(leftTime) && leftTime > 0 ? Date.now() + leftTime : undefined; + }, [leftTime]); + + const target = 'leftTime' in options ? memoLeftTime : targetDate; const [timeLeft, setTimeLeft] = useState(() => calcLeft(target));