{"id":13402394,"url":"https://github.com/glennreyes/react-countup","last_synced_at":"2025-05-14T01:04:09.896Z","repository":{"id":38243450,"uuid":"58287093","full_name":"glennreyes/react-countup","owner":"glennreyes","description":"💫 A configurable React component wrapper around CountUp.js","archived":false,"fork":false,"pushed_at":"2024-04-01T04:47:14.000Z","size":5545,"stargazers_count":1900,"open_issues_count":22,"forks_count":133,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-04-14T11:56:41.841Z","etag":null,"topics":["animation","count","counter","countup","incremental","react"],"latest_commit_sha":null,"homepage":"https://tr8tk.csb.app/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/glennreyes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-07T22:33:55.000Z","updated_at":"2024-05-01T05:30:56.692Z","dependencies_parsed_at":"2023-02-14T18:31:26.550Z","dependency_job_id":"410720d9-fbcb-4388-9e26-62afd905e022","html_url":"https://github.com/glennreyes/react-countup","commit_stats":{"total_commits":887,"total_committers":34,"mean_commits":26.08823529411765,"dds":0.6516347237880495,"last_synced_commit":"d06cb9a3df4435dd880f3c52ab2f6aa915e0400f"},"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glennreyes%2Freact-countup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glennreyes%2Freact-countup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glennreyes%2Freact-countup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glennreyes%2Freact-countup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/glennreyes","download_url":"https://codeload.github.com/glennreyes/react-countup/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248252691,"owners_count":21072699,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","count","counter","countup","incremental","react"],"created_at":"2024-07-30T19:01:15.442Z","updated_at":"2025-04-10T16:29:26.671Z","avatar_url":"https://github.com/glennreyes.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","React","UI Animation"],"sub_categories":["React Components","Syntax highlighting"],"readme":"# [React CountUp](https://tr8tk.csb.app/)\n\n[![GitHub license](https://img.shields.io/npm/l/react-countup.svg?style=flat-square)](https://github.com/glennreyes/react-countup/blob/master/LICENSE)\n[![Build Status](https://img.shields.io/travis/glennreyes/react-countup.svg?style=flat-square)](https://travis-ci.org/glennreyes/react-countup)\n[![Coverage Status](https://img.shields.io/coveralls/glennreyes/react-countup.svg?style=flat-square)](https://coveralls.io/github/glennreyes/react-countup)\n[![Version](https://img.shields.io/npm/v/react-countup.svg?style=flat-square)](https://www.npmjs.com/package/react-countup)\n[![Downloads](https://img.shields.io/npm/dm/react-countup.svg?style=flat-square)](http://www.npmtrends.com/react-countup)\n[![Gzip size](https://img.badgesize.io/https://unpkg.com/react-countup?style=flat-square\u0026compression=gzip)](https://img.badgesize.io/https://unpkg.com/react-countup)\n\nA configurable React component wrapper around [CountUp.js](https://inorganik.github.io/countUp.js/).\n\nClick [here](https://codesandbox.io/s/github/glennreyes/react-countup/tree/master/demo?fontsize=14\u0026hidenavigation=1\u0026theme=dark\u0026view=preview) to view on CodeSandbox.\n\n### Previous docs\n\n- [v3.x](https://github.com/glennreyes/react-countup/tree/d0002932dac8a274f951e53b1d9b1f4719176147)\n- [v4.x](https://github.com/glennreyes/react-countup/tree/afd39ca66a317271ad3135b0a924b86e2982f207)\n- [v5.x](https://github.com/glennreyes/react-countup/tree/ae4586c9f502fba726ff2d24d215c88d8f4879d7)\n\n![react-countup](https://user-images.githubusercontent.com/5080854/43985960-0a7fb776-9d0c-11e8-8082-975b1e8bf51c.gif)\n\n## Table of Contents\n\n- [Installation](#installation)\n  - [Usage](#usage)\n    - [Simple example](#simple-example)\n    - [Render prop example](#render-prop-example)\n    - [More examples](#more-examples)\n      - [Manually start with render prop](#manually-start-with-render-prop)\n      - [Autostart with render prop](#autostart-with-render-prop)\n      - [Delay start](#delay-start)\n      - [Hook](#hook)\n  - [API](#api)\n    - [Props](#props)\n      - [`className: string`](#classname-string)\n      - [`decimal: string`](#decimal-string)\n      - [`decimals: number`](#decimals-number)\n      - [`delay: ?number`](#delay-number)\n      - [`duration: number`](#duration-number)\n      - [`end: number`](#end-number)\n      - [`prefix: string`](#prefix-string)\n      - [`redraw: boolean`](#redraw-boolean)\n      - [`preserveValue: boolean`](#preservevalue-boolean)\n      - [`separator: string`](#separator-string)\n      - [`start: number`](#start-number)\n      - [`plugin: CountUpPlugin`](#plugin-countupplugin)\n      - [`startOnMount: boolean`](#startonmount-boolean)\n      - [`suffix: string`](#suffix-string)\n      - [`useEasing: boolean`](#useeasing-boolean)\n      - [`useGrouping: boolean`](#usegrouping-boolean)\n      - [`useIndianSeparators: boolean`](#useindianseparators-boolean)\n      - [`easingFn: (t: number, b: number, c: number, d: number) =\u003e number`](#easingfn-t-number-b-number-c-number-d-number--number)\n      - [`formattingFn: (value: number) =\u003e string`](#formattingfn-value-number--string)\n      - [`enableScrollSpy: boolean`](#enablescrollspy-boolean)\n      - [`scrollSpyDelay: number`](#scrollspydelay-number)\n      - [`scrollSpyOnce: boolean`](#scrollspyonce-boolean)\n      - [`onEnd: ({ pauseResume, reset, start, update }) =\u003e void`](#onend--pauseresume-reset-start-update---void)\n      - [`onStart: ({ pauseResume, reset, update }) =\u003e void`](#onstart--pauseresume-reset-update---void)\n      - [`onPauseResume: ({ reset, start, update }) =\u003e void`](#onpauseresume--reset-start-update---void)\n      - [`onReset: ({ pauseResume, start, update }) =\u003e void`](#onreset--pauseresume-start-update---void)\n      - [`onUpdate: ({ pauseResume, reset, start }) =\u003e void`](#onupdate--pauseresume-reset-start---void)\n    - [Render props](#render-props)\n      - [`countUpRef: () =\u003e void`](#countupref---void)\n      - [`pauseResume: () =\u003e void`](#pauseresume---void)\n      - [`reset: () =\u003e void`](#reset---void)\n      - [`start: () =\u003e void`](#start---void)\n      - [`update: (newEnd: number?) =\u003e void`](#update-newend-number--void)\n  - [Protips](#protips)\n    - [Trigger of transition](#trigger-of-transition)\n    - [Run if in focus](#run-if-in-focus)\n    - [Set accessibility properties for occupation period](#set-accessibility-properties-for-occupation-period)\n  - [License](#license)\n\n## Installation\n\n```bash\nyarn add react-countup\n```\n\n## Usage\n\n```js\nimport CountUp from 'react-countup';\n```\n\n### Simple example\n\n```js\n\u003cCountUp end={100} /\u003e\n```\n\nThis will start a count up transition from `0` to `100` on render.\n\n### Render prop example\n\n```js\n\u003cCountUp\n  start={-875.039}\n  end={160527.012}\n  duration={2.75}\n  separator=\" \"\n  decimals={4}\n  decimal=\",\"\n  prefix=\"EUR \"\n  suffix=\" left\"\n  onEnd={() =\u003e console.log('Ended! 👏')}\n  onStart={() =\u003e console.log('Started! 💨')}\n\u003e\n  {({ countUpRef, start }) =\u003e (\n    \u003cdiv\u003e\n      \u003cspan ref={countUpRef} /\u003e\n      \u003cbutton onClick={start}\u003eStart\u003c/button\u003e\n    \u003c/div\u003e\n  )}\n\u003c/CountUp\u003e\n```\n\nThe transition won't start on initial render as it needs to be triggered manually here.\n\n\u003e Tip: If you need to start the render prop component immediately, you can set delay={0}.\n\n### More examples\n\n#### Manually start with render prop\n\n```js\n\u003cCountUp start={0} end={100}\u003e\n  {({ countUpRef, start }) =\u003e (\n    \u003cdiv\u003e\n      \u003cspan ref={countUpRef} /\u003e\n      \u003cbutton onClick={start}\u003eStart\u003c/button\u003e\n    \u003c/div\u003e\n  )}\n\u003c/CountUp\u003e\n```\n\n#### Autostart with render prop\n\nRender start value but start transition on first render:\n\n```js\n\u003cCountUp start={0} end={100} delay={0}\u003e\n  {({ countUpRef }) =\u003e (\n    \u003cdiv\u003e\n      \u003cspan ref={countUpRef} /\u003e\n    \u003c/div\u003e\n  )}\n\u003c/CountUp\u003e\n```\n\nNote that `delay={0}` will automatically start the count up.\n\n#### Delay start\n\n```js\n\u003cCountUp delay={2} end={100} /\u003e\n```\n\n### Hook\n\n#### Simple example\n\n```js\nimport { useCountUp } from 'react-countup';\n\nconst SimpleHook = () =\u003e {\n  useCountUp({ ref: 'counter', end: 1234567 });\n  return \u003cspan id=\"counter\" /\u003e;\n};\n```\n\n#### Complete example\n\n```js\nimport { useCountUp } from 'react-countup';\n\nconst CompleteHook = () =\u003e {\n  const countUpRef = React.useRef(null);\n  const { start, pauseResume, reset, update } = useCountUp({\n    ref: countUpRef,\n    start: 0,\n    end: 1234567,\n    delay: 1000,\n    duration: 5,\n    onReset: () =\u003e console.log('Resetted!'),\n    onUpdate: () =\u003e console.log('Updated!'),\n    onPauseResume: () =\u003e console.log('Paused or resumed!'),\n    onStart: ({ pauseResume }) =\u003e console.log(pauseResume),\n    onEnd: ({ pauseResume }) =\u003e console.log(pauseResume),\n  });\n  return (\n    \u003cdiv\u003e\n      \u003cdiv ref={countUpRef} /\u003e\n      \u003cbutton onClick={start}\u003eStart\u003c/button\u003e\n      \u003cbutton onClick={reset}\u003eReset\u003c/button\u003e\n      \u003cbutton onClick={pauseResume}\u003ePause/Resume\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e update(2000)}\u003eUpdate to 2000\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n## API\n\n### Props\n\n#### `className: string`\n\nCSS class name of the span element.\n\n\u003e Note: This won't be applied when using CountUp with render props.\n\n#### `decimal: string`\n\nSpecifies decimal character.\n\nDefault: `.`\n\n#### `decimals: number`\n\nAmount of decimals to display.\n\nDefault: `0`\n\n#### `delay: number`\n\nDelay in seconds before starting the transition.\n\nDefault: `null`\n\n\u003e Note: `delay={0}` will automatically start the count up.\n\n#### `duration: number`\n\nDuration in seconds.\n\nDefault: `2`\n\n#### `end: number`\n\nTarget value.\n\n#### `prefix: string`\n\nStatic text before the transitioning value.\n\n#### `redraw: boolean`\n\nForces count up transition on every component update.\n\nDefault: `false`\n\n#### `preserveValue: boolean`\n\nSave previously ended number to start every new animation from it.\n\nDefault: `false`\n\n#### `separator: string`\n\nSpecifies character of thousands separator.\n\n#### `start: number`\n\nInitial value.\n\nDefault: `0`\n\n#### `plugin: CountUpPlugin`\n\nDefine plugin for alternate animations\n\n#### `startOnMount: boolean`\n\nUse for start counter on mount for hook usage.\n\nDefault: `true`\n\n#### `suffix: string`\n\nStatic text after the transitioning value.\n\n#### `useEasing: boolean`\n\nEnables easing. Set to `false` for a linear transition.\n\nDefault: `true`\n\n#### `useGrouping: boolean`\n\nEnables grouping with [separator](#separator-string).\n\nDefault: `true`\n\n#### `useIndianSeparators: boolean`\n\nEnables grouping using indian separation, f.e. 1,00,000 vs 100,000\n\nDefault: `false`\n\n#### `easingFn: (t: number, b: number, c: number, d: number) =\u003e number`\n\nEasing function. Click [here](http://robertpenner.com/easing) for more details.\n\nDefault: [`easeInExpo`](https://github.com/inorganik/countUp.js/blob/master/countUp.js#L103-L106)\n\n#### `formattingFn: (value: number) =\u003e string`\n\nFunction to customize the formatting of the number.\n\nTo prevent component from unnecessary updates this function should be memoized with [useCallback](https://reactjs.org/docs/hooks-reference.html#usecallback)\n\n#### `enableScrollSpy: boolean`\n\nEnables start animation when target is in view.\n\n#### `scrollSpyDelay: number`\n\nDelay (ms) after target comes into view\n\n#### `scrollSpyOnce: boolean`\n\nRun scroll spy only once\n\n#### `onEnd: ({ pauseResume, reset, start, update }) =\u003e void`\n\nCallback function on transition end.\n\n#### `onStart: ({ pauseResume, reset, update }) =\u003e void`\n\nCallback function on transition start.\n\n#### `onPauseResume: ({ reset, start, update }) =\u003e void`\n\nCallback function on pause or resume.\n\n#### `onReset: ({ pauseResume, start, update }) =\u003e void`\n\nCallback function on reset.\n\n#### `onUpdate: ({ pauseResume, reset, start }) =\u003e void`\n\nCallback function on update.\n\n### Render props\n\n#### `countUpRef: () =\u003e void`\n\nRef to hook the countUp instance to\n\n#### `pauseResume: () =\u003e void`\n\nPauses or resumes the transition\n\n#### `reset: () =\u003e void`\n\nResets to initial value\n\n#### `start: () =\u003e void`\n\nStarts or restarts the transition\n\n#### `update: (newEnd: number?) =\u003e void`\n\nUpdates transition to the new end value (if given)\n\n## Protips\n\n### Trigger of transition\n\nBy default, the animation is triggered if any of the following props has changed:\n\n- `duration`\n- `end`\n- `start`\n\nIf `redraw` is set to `true` your component will start the transition on every component update.\n\n### Run if in focus\n\nYou need to check if your counter in viewport, [react-visibility-sensor](https://github.com/joshwnj/react-visibility-sensor) can be used for this purpose.\n\n```js\nimport React from 'react';\nimport CountUp from 'react-countup';\nimport VisibilitySensor from 'react-visibility-sensor';\nimport './styles.css';\n\nexport default function App() {\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cdiv className=\"content\" /\u003e\n      \u003cVisibilitySensor partialVisibility offset={{ bottom: 200 }}\u003e\n        {({ isVisible }) =\u003e (\n          \u003cdiv style={{ height: 100 }}\u003e\n            {isVisible ? \u003cCountUp end={1000} /\u003e : null}\n          \u003c/div\u003e\n        )}\n      \u003c/VisibilitySensor\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n\u003e Note: For latest **react-countup** releases there are new options [`enableScrollSpy`](#enablescrollspy-boolean) and [`scrollSpyDelay`](#scrollspydelay-number) which enable scroll spy, so that as user scrolls to the target element, it begins counting animation automatically once it has scrolled into view.\n\n```js\nimport './styles.css';\nimport CountUp, { useCountUp } from 'react-countup';\n\nexport default function App() {\n  useCountUp({\n    ref: 'counter',\n    end: 1234567,\n    enableScrollSpy: true,\n    scrollSpyDelay: 1000,\n  });\n\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cdiv className=\"content\" /\u003e\n      \u003cCountUp end={100} enableScrollSpy /\u003e\n      \u003cbr /\u003e\n      \u003cspan id=\"counter\" /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n### Set accessibility properties for occupation period\n\nYou can use callback properties to control accessibility:\n\n```js\nimport React from 'react';\nimport CountUp, { useCountUp } from 'react-countup';\n\nexport default function App() {\n  useCountUp({ ref: 'counter', end: 10, duration: 2 });\n  const [loading, setLoading] = React.useState(false);\n\n  const onStart = () =\u003e {\n    setLoading(true);\n  };\n\n  const onEnd = () =\u003e {\n    setLoading(false);\n  };\n\n  const containerProps = {\n    'aria-busy': loading,\n  };\n\n  return (\n    \u003c\u003e\n      \u003cCountUp\n        end={123457}\n        duration=\"3\"\n        onStart={onStart}\n        onEnd={onEnd}\n        containerProps={containerProps}\n      /\u003e\n      \u003cdiv id=\"counter\" aria-busy={loading} /\u003e\n    \u003c/\u003e\n  );\n}\n```\n\n### Plugin usage\n\n```js\nimport { CountUp } from 'countup.js';\nimport { Odometer } from 'odometer_countup';\n\nexport default function App() {\n  useCountUp({\n    ref: 'counter',\n    end: 1234567,\n    enableScrollSpy: true,\n    scrollSpyDelay: 1000,\n    plugin: Odometer,\n  });\n\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cspan id=\"counter\" /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglennreyes%2Freact-countup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglennreyes%2Freact-countup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglennreyes%2Freact-countup/lists"}