{"id":15415866,"url":"https://github.com/davidje13/react-hook-countdown","last_synced_at":"2025-09-11T18:36:58.123Z","repository":{"id":143905447,"uuid":"177315525","full_name":"davidje13/react-hook-countdown","owner":"davidje13","description":"countdown hook for react functional components","archived":false,"fork":false,"pushed_at":"2022-09-17T16:06:17.000Z","size":122,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T13:47:05.809Z","etag":null,"topics":["countdown","react","react-hook"],"latest_commit_sha":null,"homepage":"","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/davidje13.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":"2019-03-23T16:53:16.000Z","updated_at":"2023-01-17T09:32:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"6c4279fd-b6e0-42da-ab66-284cb53588e2","html_url":"https://github.com/davidje13/react-hook-countdown","commit_stats":{"total_commits":31,"total_committers":1,"mean_commits":31.0,"dds":0.0,"last_synced_commit":"d6cf1ad59c165b55589d7662c9404f93de037a01"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-hook-countdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-hook-countdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-hook-countdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Freact-hook-countdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidje13","download_url":"https://codeload.github.com/davidje13/react-hook-countdown/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249711651,"owners_count":21314282,"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":["countdown","react","react-hook"],"created_at":"2024-10-01T17:10:03.312Z","updated_at":"2025-04-19T14:23:30.036Z","avatar_url":"https://github.com/davidje13.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React useCountdown hook\n\nProvides a hook for React which updates at a regular interval until a\ntarget time is reached.\n\nSee the [examples](#examples) for other use cases.\n\n## Install dependency\n\n```bash\nnpm install --save react-hook-final-countdown\n```\n\n## Usage\n\n```jsx\nconst useCountdown = require('react-hook-final-countdown');\n\nconst MyComponent = ({targetTime}) =\u003e {\n  const remaining = useCountdown(targetTime, 1000);\n\n  if (remaining \u003e= 0) {\n    return (\u003cdiv\u003eSeconds remaining: {remaining / 1000}\u003c/div\u003e);\n  }\n  return (\u003cdiv\u003eCountdown ended!\u003c/div\u003e);\n};\n```\n\n## API\n\n```js\nconst remaining = useCountdown(targetTime, interval);\n\nconst time = useTimeInterval(interval[, anchorTime]);\n\nconst after = useIsAfter(time);\n\nconst before = useIsBefore(time);\n```\n\nAll times are in milliseconds. All parameters can be changed\ndynamically.\n\n### `useCountdown(targetTime, interval)`\n\nCounts down to the given target time.\n\n- `targetTime`: the timestamp to count down to (milliseconds since the\n  unix epoch).\n- `interval`: number of milliseconds between refreshes; this will\n  control how often the component is re-rendered, and will be used to\n  quantise the returned remaining milliseconds.\n\nThe returned value is -1 after the target time has been reached. Until\nthen, it is the remaining number of milliseconds quantised by the\nrequested interval (rounded down).\n\nFor example, for an interval of 800ms, returned values may be:\n\n- 2400\n- 1600\n- 800\n- 0\n- -1\n\nPositive returned values will always be a multiple of the requested\ninterval (to within numeric precision).\n\n### `useTimeInterval(interval[, anchorTime])`\n\nProvides an infinite timer, updating every `interval` milliseconds.\n\n- `interval`: number of milliseconds between refreshes; this will\n  control how often the component is re-rendered, and will be used to\n  quantise the returned time.\n- `anchorTime`: a time which can be in the future or the past; this\n  will control the \"phase\" of the clock. For example, setting\n  `interval` to 1000 and `anchorTime` to 500 will cause an update\n  every second on the half-second boundary. Defaults to 0.\n\nReturns the current timestamp, quantised using `interval`.\n\n### `useIsAfter(targetTime)`\n\nA convenience wrapper around `useCountdown`. Equivalent to:\n\n```js\nuseCountdown(targetTime, POSITIVE_INFINITY) \u003c 0\n```\n\n- `targetTime`: the timestamp to wait for (milliseconds since the\n  unix epoch).\n\nReturns false until the target time is reached, then true.\n\n### `useIsBefore(targetTime)`\n\nA convenience wrapper around `useCountdown`. Equivalent to:\n\n```js\nuseCountdown(targetTime, POSITIVE_INFINITY) \u003e= 0\n```\n\n- `targetTime`: the timestamp to wait for (milliseconds since the\n  unix epoch).\n\nReturns true until the target time is reached, then false.\n\n### `\u003cTimeProvider scheduler={scheduler}\u003e`\n\nAn entry point to manipulate the flow of time (e.g. for testing).\n\n```jsx\nconst myScheduler = {\n  getTime: () =\u003e Date.now(),\n  schedule: (fn, target) =\u003e {\n    const tm = setTimeout(fn, target - Date.now());\n    return () =\u003e clearTimeout(fn);\n  },\n};\n\nconst MyApp = () =\u003e (\n  \u003cTimeProvider scheduler={myScheduler}\u003e\n    \u003cMyComponent /\u003e\n  \u003c/TimeProvider\u003e\n);\n```\n\nBy default, a `Scheduler` with default parameters is used. When using\ncustom scheduling, it is recommended that you configure or wrap a\n`Scheduler` rather than creating a new implementation from scratch\n(e.g. see the [\"half speed\" example below](#custom-time-flow-half-speed)).\n\nNote that it is not possible to change the `scheduler` parameter; if\nyou need to change the scheduler dynamically, do so within the\nscheduler itself.\n\n### `new Scheduler(options)`\n\nA class which provides scheduling ability, including aggregation of\nmultiple scheduled tasks and throttling when the page is not visible.\n\n```jsx\nconst myScheduler = new Scheduler({\n  getTime: Date.now,\n  visibleThrottle: 10,\n  hiddenThrottle: 500,\n});\n\nconst MyApp = () =\u003e (\n  \u003cTimeProvider scheduler={myScheduler}\u003e\n    \u003cMyComponent /\u003e\n  \u003c/TimeProvider\u003e\n);\n```\n\n- `options`: configuration options for the scheduler:\n  - `getTime`: a function which returns time since an epoch in\n    milliseconds. Defaults to `Date.now`.\n  - `visibleThrottle`: a minimum delay to apply when the page is\n    visible (i.e. the browser tab is selected). Defaults to 10ms.\n  - `hiddenThrottle`: a minimum delay to apply when the page is\n    not visible (i.e. another browser tab is selected).\n    Defaults to 500ms to reduce load on the client CPU.\n    When the page regains focus, all timers will be checked (as\n    the timers may slip while the window is not visible in many\n    browsers)\n\nIf you provide a custom `getTime` implementation, note that the\nscheduled tasks will still assume that the time will increment in\nreal-time (i.e. its value will increase by 1000 every second). If\nyou want to modify the flow of time, you will need to use a wrapper\naround `schedule` (e.g. see the\n[\"half speed\" example below](#custom-time-flow-half-speed)).\n\nThis class is designed for use with the `TimeProvider`, but can\nalso be used independently:\n\n```js\nconst myScheduler = new Scheduler({\n  getTime: Date.now,\n  visibleThrottle: 10,\n  hiddenThrottle: 500,\n});\n\nconst now = myScheduler.getTime();\nconst cancel = myScheduler.schedule(myFn, now + 5000);\n// in 5 seconds, myFn will be invoked,\n// or call cancel() to cancel the task\n```\n\n## Examples\n\n### A countdown to the year 3000\n\n```jsx\nconst {useCountdown} = require('react-hook-final-countdown');\n\nconst Y3K = Date.UTC(3000);\n\nconst MyComponent = () =\u003e {\n  const remaining = useCountdown(Y3K, 1000);\n\n  if (remaining \u003e= 0) {\n    return (\u003cdiv\u003eSeconds remaining: {remaining / 1000}\u003c/div\u003e);\n  }\n  return (\u003cdiv\u003eHappy new year!\u003c/div\u003e);\n};\n```\n\n### A button which is disabled for a short time when first displayed\n\n```jsx\nconst {useIsAfter} = require('react-hook-final-countdown');\n\nconst MyDelayedButton = ({onClick}) =\u003e {\n  const [firstRenderedTime] = useState(Date.now());\n  const enabled = useIsAfter(firstRenderedTime + 1000);\n\n  return (\u003cbutton disabled={!enabled} onClick={onClick}\u003eContinue\u003c/button\u003e);\n};\n```\n\n### A button which prevents rapid clicking\n\n```jsx\nconst {useIsAfter} = require('react-hook-final-countdown');\n\nconst MyDelayedButton = ({onClick}) =\u003e {\n  const [lastClicked, setLastClicked] = useState(Number.NEGATIVE_INFINITY);\n  const enabled = useIsAfter(lastClicked + 1000);\n  const clickHandler = () =\u003e {\n    setLastClicked(Date.now());\n    onClick();\n  };\n\n  return (\u003cbutton disabled={!enabled} onClick={clickHandler}\u003eContinue\u003c/button\u003e);\n};\n```\n\n### A clock\n\n```jsx\nconst {useTimeInterval} = require('react-hook-final-countdown');\n\nconst MyClock = () =\u003e {\n  const time = useTimeInterval(1000);\n\n  return (\u003cspan\u003e{new Date(time).toString()}\u003c/span\u003e);\n};\n```\n\n### Custom time flow (half speed)\n\n```jsx\nconst {Scheduler, TimeProvider} = require('react-hook-final-countdown');\n\nconst scheduler = new Scheduler();\nconst slowMotionScheduler = {\n  getTime: () =\u003e scheduler.getTime() * 0.5,\n  schedule: (fn, target) =\u003e scheduler.schedule(fn, target * 2),\n};\n\nconst MySlowMotionApp = () =\u003e (\n  \u003cTimeProvider scheduler={slowMotionScheduler}\u003e\n    \u003cMyComponent /\u003e\n  \u003c/TimeProvider\u003e\n);\n```\n\n### Custom time flow (static snapshot-in-time)\n\n```jsx\nconst {TimeProvider} = require('react-hook-final-countdown');\n\nconst time = Date.UTC(2000);\nconst frozenScheduler = {\n  getTime: () =\u003e time, // fixed time\n  schedule: (fn, target) =\u003e () =\u003e null, // no-op\n};\n\nconst MyFrozenApp = () =\u003e (\n  \u003cTimeProvider scheduler={frozenScheduler}\u003e\n    \u003cMyComponent /\u003e\n  \u003c/TimeProvider\u003e\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Freact-hook-countdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidje13%2Freact-hook-countdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Freact-hook-countdown/lists"}