Skip to main content

Overview

The useCountdown hook provides a countdown timer that updates every second and triggers a callback when the timer expires. It’s primarily used for quote expiration tracking.

Import

import { useCountdown } from '@/lib/hooks';

Signature

function useCountdown(
  timestamp: number,
  onExpire?: () => void
): {
  timeLeft: number;
  formattedTime: string;
  isExpired: boolean;
}

Parameters

timestamp
number
required
Unix timestamp (in seconds) when the countdown should expire
onExpire
() => void
Optional callback function to execute when the countdown reaches zero

Return Value

timeLeft
number
Number of seconds remaining until expiration
formattedTime
string
Formatted time string showing remaining seconds, or β€œExpired” when done
isExpired
boolean
True when the countdown has reached zero

Usage Examples

Basic Countdown

import { useCountdown } from '@/lib/hooks';

function CountdownDisplay({ expirationTimestamp }: { expirationTimestamp: number }) {
  const { timeLeft, formattedTime, isExpired } = useCountdown(expirationTimestamp);
  
  return (
    <div>
      {isExpired ? (
        <span>Time expired!</span>
      ) : (
        <span>{timeLeft} seconds remaining</span>
      )}
    </div>
  );
}

Quote Expiration Timer

import { useCountdown } from '@/lib/hooks';

function QuoteCountdown({ 
  expirationTimestamp, 
  onRefresh 
}: { 
  expirationTimestamp: number;
  onRefresh: () => void;
}) {
  const { timeLeft, isExpired } = useCountdown(
    expirationTimestamp,
    onRefresh // Auto-refresh when expired
  );
  
  return (
    <div>
      <p>Quote expires in: {timeLeft}s</p>
      {isExpired && <button onClick={onRefresh}>Get New Quote</button>}
    </div>
  );
}

With Visual Progress

import { useCountdown } from '@/lib/hooks';

function ProgressCountdown({ expirationTimestamp }: { expirationTimestamp: number }) {
  const TOTAL_SECONDS = 30;
  const { timeLeft, formattedTime } = useCountdown(expirationTimestamp);
  
  const percentageLeft = (timeLeft / TOTAL_SECONDS) * 100;
  
  return (
    <div>
      <div className="progress-bar">
        <div 
          className="progress-fill" 
          style={{ width: `${percentageLeft}%` }}
        />
      </div>
      <span>{formattedTime}</span>
    </div>
  );
}

QuoteCountdown Component

The actual QuoteCountdown component in the application uses this hook:
components/QuoteCountdown.tsx
import { useCountdown } from '@/lib/hooks';
import { Clock } from 'lucide-react';

export const QuoteCountdown = ({
  expirationTimestamp,
  onExpire,
}: {
  expirationTimestamp: number;
  onExpire: () => void;
}) => {
  const { timeLeft, isExpired } = useCountdown(expirationTimestamp, onExpire);

  return (
    <div className="flex items-center gap-2 text-sm">
      <Clock className="h-4 w-4" />
      <span>
        {isExpired ? 'Quote expired' : `Quote expires in ${timeLeft}s`}
      </span>
    </div>
  );
};

Implementation Details

Automatic Cleanup

The hook automatically cleans up the interval timer when:
  • The component unmounts
  • The timestamp parameter changes
  • The countdown reaches zero
useEffect(() => {
  const timer = setInterval(() => {
    // Update countdown
  }, 1000);

  return () => clearInterval(timer); // Cleanup
}, [timestamp, onExpire]);

Time Calculation

The countdown calculates remaining time by:
  1. Converting Unix timestamp (seconds) to milliseconds
  2. Subtracting current time
  3. Flooring to nearest second
  4. Clamping to zero minimum
const calculateTimeLeft = () => {
  const difference = timestamp * 1000 - Date.now();
  return Math.max(0, Math.floor(difference / 1000));
};

Best Practices

Use with quote expiration

Quotes from the OneBalance API have a 30-second validity period. Use this hook to track expiration and automatically refresh quotes.

Provide expiration callback

Always pass an onExpire callback to handle what should happen when the timer runs out (e.g., refresh quote, show warning).

Handle edge cases

Check isExpired before allowing users to execute actions based on the countdown (e.g., prevent swap execution with expired quote).
  • useQuotes - Uses countdown for quote expiration tracking
  • QuoteDetails - Displays quote information with countdown
  • SwapForm - Uses countdown for quote validity

Build docs developers (and LLMs) love