amrlabib / react-timer-hook

React timer hook
https://www.npmjs.com/package/react-timer-hook
MIT License
515 stars 112 forks source link

Start function in UseStopwatch Demo not working as Expected #81

Open Youky1 opened 2 years ago

Youky1 commented 2 years ago

When I click the start button multiple times after pausing, it always starts timing from the last paused time

fauzanss commented 1 year ago

you can use reset function before call start function when u want to reset the time from the beginning

tlmader commented 2 months ago

Adding a key to the component containing the timer to force a remount also does the trick.

Here's my component that resets the timer when the expiryTimestamp prop changes:

import { Clock, Hourglass } from '@tamagui/lucide-icons';
import { FC, useEffect } from 'react';
import { useTimer } from 'react-timer-hook';
import { SizableText, XStack } from 'tamagui';
import { ICON_SIZE_$3, OPACITY_LIGHT } from '../../core/theme/constants';

type ActivityCardTimerProps = {
  /**
   * True if waiting for the next event.
   */
  completed?: boolean;
  expiryTimestamp: Date;
  onExpire: () => void;
  prefix?: string;
  suffix?: string;
};
export const ActivityCardTimer: FC<ActivityCardTimerProps> = (props) => {
  return (
    <ActivityCardTimerInner
      {...props}
      key={props.expiryTimestamp.toISOString()} // Forces timer to restart
    />
  );
};

const ActivityCardTimerInner: FC<ActivityCardTimerProps> = ({
  completed,
  expiryTimestamp,
  onExpire,
  prefix = 'Next in',
  suffix = 'left',
}) => {
  const { days, hours, minutes, seconds, restart, isRunning } = useTimer({
    expiryTimestamp,
    onExpire,
    autoStart: true,
  });
  if (days === 0 && minutes < 1) {
    console.log({ days, hours, minutes, seconds, isRunning });
  }
  useEffect(() => {
    if (expiryTimestamp) {
      restart(expiryTimestamp, true);
    }
  }, [expiryTimestamp, restart]);
  const expiring = days === 0;
  const formattedHours = String(hours).padStart(2, '0');
  const formattedMinutes = String(minutes).padStart(2, '0');
  const formattedSeconds = String(seconds).padStart(2, '0');
  if (completed) {
    return (
      <XStack alignItems="center" gap="$2" opacity={OPACITY_LIGHT}>
        <Hourglass size={ICON_SIZE_$3} />
        {expiring ? (
          <SizableText>
            {prefix} {formattedHours}:{formattedMinutes}:{formattedSeconds}
          </SizableText>
        ) : (
          <SizableText size="$3">
            {prefix} {days} days
          </SizableText>
        )}
      </XStack>
    );
  }
  return (
    <XStack alignItems="center" gap="$2" opacity={expiring ? 1 : OPACITY_LIGHT}>
      <Clock size={ICON_SIZE_$3} color={expiring ? '$red11' : undefined} />
      {expiring ? (
        <SizableText color={expiring ? '$red11' : undefined}>
          {formattedHours}:{formattedMinutes}:{formattedSeconds} {suffix}
        </SizableText>
      ) : (
        <SizableText size="$3">
          {days} days {suffix}
        </SizableText>
      )}
    </XStack>
  );
};