Package detail

use-count-up

vydimitrov144.3kMIT3.0.1

React/React Native component and hook to animate counting up or down to a number

react, reactjs, react-native, animate-numerical-value

readme

use-count-up

NPM version Weekly downloads Code Coverage Bundle Size


React/React Native component and hook to animate
counting up or down to a number


Key features

:trophy: Lighter implementation and smaller bundle size in comparison with similar feature solutions
:flags: Declarative API (no more imperative calls to start() and update())
 :iphone:  React Native support for iOS and Android
:deciduous_tree: Tree-shakable
 :file_cabinet: Server-side rendering (SSR) compatibility

Installation

yarn add use-count-up

Demo

Check the React demo on CodeSandbox and React Native demo on Expo Snack to get started.

Component basic usage

import { CountUp } from 'use-count-up'

const MyComponent = () => <CountUp isCounting end={1320} duration={3.2} />

The CountUp component should be wrapped in a Text component when used in a React Native project like so:

import { Text } from 'react-native'
import { CountUp } from 'use-count-up'

const MyComponent = () => (
  <Text>
    <CountUp isCounting end={1320} duration={3.2} />
  </Text>
)

Hook basic usage

The hook accepts the same properties as the component. The usage for React and React Native is the same.

import { useCountUp } from 'use-count-up'

const MyComponent = () => {
  const { value } = useCountUp({
    isCounting: true,
    end: 1320,
    duration: 3.2,
  })

  return value
}

Props

The component and the hook accept the same props. They are fully interchangeable.

Prop Name Type Default Description
isCounting boolean false Play and pause counting animation
start number 0 Initial value
end number - Target value
duration number - Animation duration in seconds. Defaults to 2 seconds if end is set
decimalPlaces number - Number of decimal places after the decimal separator. Defaults to the max decimal places count from start and end props
decimalSeparator string - Decimal separator character
thousandsSeparator string - Thousands separator character
easing string \ function easeOutCubic _Type: easeOutCubic \ easeInCubic \ linear \ easing func_
Easing function to control the animation progress
formatter function - _Type: (value: number) => number \ string \ node_
A function that formats the output value. It has the highest priority so all other formatting options are ignored
updateInterval number 0 Update interval in seconds. Determines how often the animated value will change. When set to 0 the value will update on each key frame
children function - _Type: ({ value: number, reset: () => void }) => number \ string \ node_
CountUp component - children prop
onComplete function - _Type: () => void \ {shouldRepeat: boolean, delay: number}_
On complete handler. Repeat animation by returning an object with shouldRepeat equals true and delay in seconds.
onUpdate function - _Type: (currentValue: number \ string \ node) => void_
On value update event handler

Return values

The hook returns the current count up value and reset method to reset the animation.

import { useCountUp } from 'use-count-up'

const { value, reset } = useCountUp({ isCounting: true })

The component's children render function will receive as props the current count up value and reset method to reset the animation.

import { CountUp } from 'use-count-up'

const MyComponent = () => (
  <CountUp isCounting>{({ value, reset }) => value}</CountUp>
)

Why use toLocaleString with formatter

Number formatting varies per language group. For example, the number 3842.45 in German will be formatted as 3.842,45 whereas in British English it will be 3,842.45 (spot the different decimal and thousands separators). Number.toLocaleString() is a built-in JS method that returns a string with a language-sensitive representation of the number. The basic implementation of the method will detect the default locale that is set up on the user's computer and will format the number accordingly. The browser support for toLocaleString is incredibly good.

If you expect variance in the geographical/country distribution of your users, then this is a must. The simplest way to use toLocaleString with the Count up component or hook is to use the formatter prop, like so:

import { CountUp } from 'use-count-up'

const MyComponent = () => (
  <CountUp
    isCounting
    end={1320}
    formatter={(value) => value.toLocaleString()}
  />
)

toLocaleString method accepts an object with two parameters, locale and options, which allows further customization of the number value. Setting up the first parameter, locale, allows the use of a specific locale and fallback option. The second parameter, options, will let you format the value in a custom way. For example, you may choose to add a min and max number of decimal places, or set currency. Keep in mind though that the locale and options arguments are not supported in all browsers.

Recipes

Reset animation

Pass a key prop to CountUp component and change it when the animation should repeat. It can be also used when a change of start or end value should start the animation over.

import { CountUp } from 'use-count-up'

const MyComponent = ({ end }) => <CountUp isCounting end={end} key={end} />

Repeat animation on completion

Return from the onComplete handler an object with key shouldRepeat: true. Optionally the delay before repeating can be set. In the example below the animation will be repeated in 2 seconds

import { CountUp } from 'use-count-up'

const onComplete = () => {
  // do your stuff here
  return { shouldRepeat: true, delay: 2 }
}

const MyComponent = () => (
  <CountUp isCounting end={4378.2} onComplete={onComplete} />
)

Count up to infinity

Don't provide end and duration props. start prop can be set to any value

import { CountUp } from 'use-count-up'

const MyComponent = () => <CountUp isCounting start={1024.4} />

Count up/down n-seconds

Set the easing to "linear" and duration to the seconds it should count up/down. The updateInterval can be set to 1, so it updates once every second. Here is an example of a 10-second count-down:

import { CountUp } from 'use-count-up'

const MyComponent = () => (
  <CountUp
    isCounting
    start={10}
    end={0}
    duration={10}
    easing="linear"
    updateInterval={1}
    onUpdate={(currentValue) => {
      // it will fire once every second
    }}
  />
)

changelog

Change Log

3.0.1 (September 5th, 2021)

Fix:

  • upgraded use-elapsed-time to 3.0.2, which fixes an issue where reset method was taking any kind of value as newStartAt value. Not it checks if the value provided is a number

3.0.0 ( September 5th , 2021)

Breaking Changes:

  • IE is not longer supported
  • autoResetKey props has been deprecated.
  • shouldUseToLocaleString and the whole setup to use the built-in toLocaleString out of the box has been deprecated. The same result can be achieved using the formatter function.
  • React PropTypes has been removed as well as the prop-types peer-dependency. The component and hook will rely on the TypeScript types.
  • prefix and suffix props has been deprecated. The same result can be achieved just by adding them to in front and behind the value.

New features:

  • updateInterval prop now determines how often the animated value will change. When set to 0 the value will update on each key frame (default behavior).
  • onUpdate callback will be fired with the current animated value when it changes.

Implemented enhancements:

  • bundle size is now even further reduced
  • esbuild is now used to bundle the code
  • example folder is added, which can be used for testing the hook and component

2.3.1 (March 25th, 2021)

Implemented enhancements:

  • chore: upgrade dependencies

2.3.0 (Jan 15th, 2021)

Implemented enhancements:

  • feat: add list of supported browsers to package.json

2.2.6 (Jan 12th, 2021)

Implemented enhancements:

  • chore: Add renovate to the repo
  • chore: Update all packages

2.2.5 (Sept 10th, 2020)

Implemented enhancements:

  • chore: upgrade rollup and rollup-terser packages

2.2.4 (June 11th, 2020)

Implemented enhancements:

  • feat: use Rollup instead of Webpack to bundle the package, which enables ES module bundles.

2.1.4 (June 8th, 2020)

Implemented enhancements:

  • chore: update list of keywords in package.json

2.1.3 (June 3rd, 2020)

Big fix:

  • fix: upgrade use-elapsed-time to 2.1.4 which fixes an issue where pausing the animation once it is completed, resetting the timer and playing again it did not work.

2.1.2 (June 1st, 2020)

Implemented enhancements:

  • fix: upgrade use-elapsed-time package to v2.1.3 which replaces useLayoutEffect with useEffect when the environment is node for SSR and removes side effects from useState so React.StrictMode works as expected in development

2.1.1 (May 21st, 2020)

Big fix:

  • fix: fix an issue where rounding numbers with bitwise shifting number | 0 caused the last number to jump

2.1.0 (May 19th, 2020)

Big fix:

  • Upgrade use-elapsed-time dependency to v 2.1.2, which fixes and issue with reset method that takes none number values

Implemented enhancements:

  • The default decimal places count is not determined based on the maximum number of decimal places in start and end. The decimal places count is also used in toLocaleString

2.0.0 (May 18th, 2020)

Breaking Changes

  • The hook now returns an object with two props: value and reset. value is the current count up value; reset is a method that reset the animation when it is fired
  • The hook now accepts a single object as an argument with all props to configure the animation.

Implemented enhancements:

  • The library exports also Count up component. The component is using the hook internally.
  • Support toLocaleString with fallback options
  • Add bunch of props to configure the output value
  • Rewrite the source code using TypeScript
  • Support React Native

1.0.4 (Nov 27th, 2019)

Minor changes:

  • Update TypeScript type definitions

1.0.3 (Nov 24th, 2019)

Minor changes:

  • Update Readme

1.0.2 (Nov 24th, 2019)

Implemented enhancements:

  • Add TypeScript type definitions

1.0.1 (Nov 13th, 2019)

Minor changes:

  • Update .gitignore, .npmignore and Readme

1.0.0 (Oct 6th, 2019)

Implemented enhancements:

  • Init the project with simple hook and returns the count up value