or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-react-countup

A configurable React component wrapper around CountUp.js for animated number counting effects

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-countup@6.5.x

To install, run

npx @tessl/cli install tessl/npm-react-countup@6.5.0

index.mddocs/

React CountUp

React CountUp is a configurable React component wrapper around CountUp.js that provides animated number counting effects. It offers both declarative component usage and imperative hook-based control with full TypeScript support.

Package Information

  • Package Name: react-countup
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install react-countup

Core Imports

import CountUp, { useCountUp, type CountUpProps } from "react-countup";

For CommonJS:

const CountUp = require("react-countup").default;
const { useCountUp } = require("react-countup");

Basic Usage

import React from "react";
import CountUp from "react-countup";

// Simple declarative usage
function App() {
  return (
    <div>
      <CountUp end={100} duration={2} />
    </div>
  );
}

// With custom formatting
function FormattedCounter() {
  return (
    <CountUp
      start={0}
      end={1234567}
      duration={3}
      separator=","
      prefix="$"
      suffix=" USD"
      decimals={2}
    />
  );
}

Architecture

React CountUp is built around three key components:

  • CountUp Component: Declarative React component supporting both standard rendering and render prop patterns
  • useCountUp Hook: Imperative hook providing programmatic control over animations with lifecycle management
  • CountUp.js Integration: Leverages the underlying CountUp.js library with React-specific optimizations and SSR compatibility

Capabilities

CountUp Component

React component wrapper providing declarative animated counting with extensive customization options and render prop support.

/**
 * React component for animated number counting
 */
declare const CountUp: React.FC<CountUpProps>;

interface CountUpProps extends CommonProps, CallbackProps {
  /** CSS class name for the container element */
  className?: string;
  /** Force redraw on every prop change */
  redraw?: boolean;
  /** Render prop function for custom rendering */
  children?: (props: RenderCounterProps) => React.ReactNode;
  /** Inline styles for the container element */
  style?: React.CSSProperties;
  /** Preserve current value when updating end value */
  preserveValue?: boolean;
  /** Additional props for the container span element */
  containerProps?: React.ComponentPropsWithoutRef<'span'>;
}

interface RenderCounterProps extends CountUpApi {
  /** Ref to attach to custom render element */
  countUpRef: React.RefObject<HTMLElement>;
}

Usage Examples:

import React from "react";
import CountUp from "react-countup";

// Standard usage
<CountUp end={100} duration={2} />

// With render prop for custom styling
<CountUp end={100} duration={2}>
  {({ countUpRef, start, reset }) => (
    <div>
      <span ref={countUpRef} className="big-number" />
      <button onClick={start}>Start</button>
      <button onClick={reset}>Reset</button>
    </div>
  )}
</CountUp>

// With event callbacks
<CountUp
  end={100}
  duration={2}
  onEnd={({ reset, start }) => console.log("Animation completed!")}
  onStart={() => console.log("Animation started!")}
/>

useCountUp Hook

Hook providing imperative control over CountUp animations with lifecycle management and programmatic API access.

/**
 * Hook for imperative CountUp control
 * @param props Configuration options for the counter
 * @returns API object with control methods
 */
function useCountUp(props: UseCountUpProps): CountUpApi;

interface UseCountUpProps extends CommonProps, CallbackProps {
  /** Target element reference (string selector or React ref) */
  ref: string | React.RefObject<HTMLElement>;
  /** Whether to reinitialize when props change */
  enableReinitialize?: boolean;
}

interface CountUpApi {
  /** Start or restart the animation */
  start: () => void;
  /** Pause or resume the animation */
  pauseResume: () => void;
  /** Reset the counter to start value */
  reset: () => void;
  /** Update the end value and animate to it */
  update: (newEnd: string | number) => void;
  /** Get the underlying CountUp.js instance */
  getCountUp: (recreate?: boolean) => CountUpInstance;
}

Usage Examples:

import React, { useRef } from "react";
import { useCountUp } from "react-countup";

function CustomCounter() {
  const countUpRef = useRef<HTMLSpanElement>(null);
  
  const { start, reset, update, pauseResume } = useCountUp({
    ref: countUpRef,
    end: 100,
    duration: 2,
    startOnMount: false,
  });

  return (
    <div>
      <span ref={countUpRef} />
      <button onClick={start}>Start</button>
      <button onClick={pauseResume}>Pause/Resume</button>
      <button onClick={reset}>Reset</button>
      <button onClick={() => update(200)}>Update to 200</button>
    </div>
  );
}

// With string selector
function SelectorCounter() {
  useCountUp({
    ref: 'counter-element',
    end: 100,
    duration: 2,
  });

  return <div id="counter-element" />;
}

Common Configuration

Core Props Interface

Shared configuration options available to both component and hook.

interface CommonProps extends CountUpInstanceProps {
  /** Whether to start animation on mount */
  startOnMount?: boolean;
  /** Delay before starting animation (in seconds) */
  delay?: number | null;
}

interface CountUpInstanceProps extends CountUpOptions {
  /** Number of decimal places to display */
  decimals?: number;
  /** The target end value */
  end: number;
  /** The starting value */
  start?: number;
  /** Whether to use easing animation */
  useEasing?: boolean;
}

Event Callbacks

Complete event callback system for animation lifecycle management.

interface CallbackProps {
  /** Called when animation ends */
  onEnd?: OnEndCallback;
  /** Called when animation starts */
  onStart?: OnStartCallback;
  /** Called when animation is paused/resumed */
  onPauseResume?: OnPauseResumeCallback;
  /** Called when counter is reset */
  onReset?: OnResetCallback;
  /** Called when end value is updated */
  onUpdate?: OnUpdateCallback;
}

type OnEndCallback = (args: OnEndArgs) => void;
type OnStartCallback = (args: OnStartArgs) => void;
type OnPauseResumeCallback = (args: OnPauseResumeArgs) => void;
type OnResetCallback = (args: OnResetArgs) => void;
type OnUpdateCallback = (args: OnUpdateArgs) => void;

interface OnEndArgs {
  pauseResume: () => void;
  reset: () => void;
  start: () => void;
  update: (newEnd: string | number) => void;
}

interface OnStartArgs {
  pauseResume: () => void;
  reset: () => void;
  update: (newEnd: string | number) => void;
}

interface OnPauseResumeArgs {
  reset: () => void;
  start: () => void;
  update: (newEnd: string | number) => void;
}

interface OnResetArgs {
  pauseResume: () => void;
  start: () => void;
  update: (newEnd: string | number) => void;
}

interface OnUpdateArgs {
  pauseResume: () => void;
  reset: () => void;
  start: () => void;
}

CountUp.js Configuration Options

All configuration options from the underlying CountUp.js library are supported:

interface CountUpOptions {
  /** Decimal character */
  decimal?: string;
  /** Thousands separator character */
  separator?: string;
  /** Text prepended to result */
  prefix?: string;
  /** Text appended to result */
  suffix?: string;
  /** Animation duration in seconds */
  duration?: number;
  /** Whether to use easing animation */
  useEasing?: boolean;
  /** Whether to use thousands separator grouping */
  useGrouping?: boolean;
  /** Whether to use Indian number separators */
  useIndianSeparators?: boolean;
  /** Custom easing function */
  easingFn?: (t: number, b: number, c: number, d: number) => number;
  /** Custom formatting function */
  formattingFn?: (value: number) => string;
  /** Custom numerals array */
  numerals?: string[];
  /** Whether to enable scroll spy functionality */
  enableScrollSpy?: boolean;
  /** Scroll spy delay in milliseconds */
  scrollSpyDelay?: number;
  /** Whether scroll spy should trigger only once */
  scrollSpyOnce?: boolean;
  /** CountUp.js plugin */
  plugin?: any;
}

/** CountUp.js instance returned by getCountUp method */
interface CountUpInstance {
  /** Start the animation */
  start(callback?: () => void): void;
  /** Pause or resume the animation */
  pauseResume(): void;
  /** Reset to start value */
  reset(): void;
  /** Update to new end value */
  update(newEnd: number | string): void;
  /** Get formatted value at current state */
  formattingFn(value: number): string;
}

Default Values

The useCountUp hook provides sensible defaults for all configuration options:

const DEFAULTS = {
  decimal: '.',
  separator: ',',
  delay: null,
  prefix: '',
  suffix: '',
  duration: 2,
  start: 0,
  decimals: 0,
  startOnMount: true,
  enableReinitialize: true,
  useEasing: true,
  useGrouping: true,
  useIndianSeparators: false,
};

Advanced Usage Patterns

Conditional Animations

import React, { useState } from "react";
import CountUp from "react-countup";

function ConditionalCounter() {
  const [shouldAnimate, setShouldAnimate] = useState(false);

  return (
    <div>
      {shouldAnimate && (
        <CountUp
          end={100}
          duration={2}
          onEnd={() => setShouldAnimate(false)}
        />
      )}
      <button onClick={() => setShouldAnimate(true)}>
        Start Animation
      </button>
    </div>
  );
}

Multiple Counters with Synchronization

import React, { useRef } from "react";
import { useCountUp } from "react-countup";

function SynchronizedCounters() {
  const ref1 = useRef<HTMLSpanElement>(null);
  const ref2 = useRef<HTMLSpanElement>(null);
  
  const counter1 = useCountUp({
    ref: ref1,
    end: 100,
    duration: 2,
    startOnMount: false,
  });
  
  const counter2 = useCountUp({
    ref: ref2,
    end: 200,
    duration: 2,
    startOnMount: false,
  });

  const startBoth = () => {
    counter1.start();
    counter2.start();
  };

  return (
    <div>
      <span ref={ref1} /> | <span ref={ref2} />
      <button onClick={startBoth}>Start Both</button>
    </div>
  );
}

Custom Formatting with Callbacks

import CountUp from "react-countup";

function CustomFormattedCounter() {
  return (
    <CountUp
      end={1234567.89}
      decimals={2}
      duration={3}
      formattingFn={(value) => {
        // Custom currency formatting
        return new Intl.NumberFormat('en-US', {
          style: 'currency',
          currency: 'USD'
        }).format(value);
      }}
    />
  );
}

Error Handling

The library handles common error scenarios:

  • Missing DOM element: When using render props, the library logs a warning if countUpRef is not attached to a DOM element
  • Invalid values: Non-numeric end values are handled gracefully by CountUp.js
  • SSR compatibility: Uses useIsomorphicLayoutEffect to prevent hydration mismatches

TypeScript Support

React CountUp provides complete TypeScript definitions with:

  • Full type safety for all props and callback parameters
  • Generic type preservation where applicable
  • Comprehensive interface definitions for all API surfaces
  • Integration with React's built-in types (CSSProperties, RefObject, etc.)

Dependencies

  • Runtime: countup.js ^2.8.0
  • Peer Dependencies: react >= 16.3.0
  • No additional runtime dependencies