{"id":33096503,"url":"https://github.com/amrlabib/react-timer-hook","last_synced_at":"2026-01-15T01:20:36.310Z","repository":{"id":37458388,"uuid":"156123732","full_name":"amrlabib/react-timer-hook","owner":"amrlabib","description":"React timer hook","archived":false,"fork":false,"pushed_at":"2025-11-15T10:44:14.000Z","size":2339,"stargazers_count":618,"open_issues_count":11,"forks_count":115,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-11-15T21:02:45.586Z","etag":null,"topics":["clock","component","countdown","days","hook","hours","javascript","minutes","react","react-hook","react-hooks","react-native","seconds","stopwatch","time","timer","timers"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/react-timer-hook","language":"TypeScript","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/amrlabib.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-11-04T20:50:20.000Z","updated_at":"2025-11-12T09:43:41.000Z","dependencies_parsed_at":"2024-01-17T15:04:43.964Z","dependency_job_id":"0b75e524-97ee-436f-ae1e-e5bd5dd21c1c","html_url":"https://github.com/amrlabib/react-timer-hook","commit_stats":null,"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/amrlabib/react-timer-hook","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amrlabib%2Freact-timer-hook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amrlabib%2Freact-timer-hook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amrlabib%2Freact-timer-hook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amrlabib%2Freact-timer-hook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amrlabib","download_url":"https://codeload.github.com/amrlabib/react-timer-hook/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amrlabib%2Freact-timer-hook/sbom","scorecard":{"id":190631,"data":{"date":"2025-08-11","repo":{"name":"github.com/amrlabib/react-timer-hook","commit":"a4abf8c26c300b05da9c041c5e5bb048249d6e0c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 1/15 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 18 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-xffm-g5w8-qvg7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-4v9v-hfq4-rm2v","Warn: Project is vulnerable to: GHSA-9jgg-88mc-972h"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T20:36:15.385Z","repository_id":37458388,"created_at":"2025-08-16T20:36:15.385Z","updated_at":"2025-08-16T20:36:15.385Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28441031,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T00:55:22.719Z","status":"ssl_error","status_checked_at":"2026-01-15T00:55:20.945Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["clock","component","countdown","days","hook","hours","javascript","minutes","react","react-hook","react-hooks","react-native","seconds","stopwatch","time","timer","timers"],"created_at":"2025-11-14T20:00:27.828Z","updated_at":"2026-01-15T01:20:36.287Z","avatar_url":"https://github.com/amrlabib.png","language":"TypeScript","readme":"## react-timer-hook\n\nReact timer hook is a custom [react hook](https://reactjs.org/docs/hooks-intro.html), built to handle timer, stopwatch, and time logic/state in your react component.\n\n1. `useTimer`: Timers (countdown timer)\n2. `useStopwatch`: Stopwatch (count up timer)\n3. `useTime`: Time (return current time)\n\n---\n\n## Setup\n\n`yarn add react-timer-hook` OR `npm install --save react-timer-hook`\n\n---\n\n## `useTimer` - [Demo](https://amrlabib.github.io/react-timer-hook/)\n\n### Example\n\n```javascript\nimport React from 'react';\nimport { useTimer } from 'react-timer-hook';\n\nfunction MyTimer({ expiryTimestamp }) {\n  const {\n    totalSeconds,\n    milliseconds,\n    seconds,\n    minutes,\n    hours,\n    days,\n    isRunning,\n    start,\n    pause,\n    resume,\n    restart,\n  } = useTimer({ expiryTimestamp, onExpire: () =\u003e console.warn('onExpire called'), interval: 20 });\n\n\n  return (\n    \u003cdiv style={{textAlign: 'center'}}\u003e\n      \u003ch1\u003ereact-timer-hook \u003c/h1\u003e\n      \u003cp\u003eTimer Demo\u003c/p\u003e\n      \u003cdiv style={{fontSize: '100px'}}\u003e\n        \u003cspan\u003e{days}\u003c/span\u003e:\u003cspan\u003e{hours}\u003c/span\u003e:\u003cspan\u003e{minutes}\u003c/span\u003e:\u003cspan\u003e{seconds}\u003c/span\u003e:\u003cspan\u003e{milliseconds}\u003c/span\u003e\n      \u003c/div\u003e\n      \u003cp\u003e{isRunning ? 'Running' : 'Not running'}\u003c/p\u003e\n      \u003cbutton onClick={start}\u003eStart\u003c/button\u003e\n      \u003cbutton onClick={pause}\u003ePause\u003c/button\u003e\n      \u003cbutton onClick={resume}\u003eResume\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e {\n        // Restarts to 5 minutes timer\n        const time = new Date();\n        time.setSeconds(time.getSeconds() + 300);\n        restart(time)\n      }}\u003eRestart\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default function App() {\n  const time = new Date();\n  time.setSeconds(time.getSeconds() + 600); // 10 minutes timer\n  return (\n    \u003cdiv\u003e\n      \u003cMyTimer expiryTimestamp={time} /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n### Settings\n\n| key | Type | Required | Description |\n| --- | --- | --- | ---- |\n| expiryTimestamp | Date object | YES | this will define for how long the timer will be running   |\n| autoStart | boolean | No | flag to decide if timer should start automatically, by default it is set to `true` |\n| interval | number | No | value to change the interval of the timer, by default it is set to 1000ms. Note: this value will not affect the timer, it will just define the frequency used to calculate the current timer values. For example, if you have a use case where milliseconds are used, you need to use a smaller value for the interval, for example, 20ms or 100ms based on your needs. |\n| onExpire | Function | No | callback function to be executed once countdown timer is expired |\n\n\n### Values\n\n| key | Type | Description |\n| --- | --- | ---- |\n| milliseconds | number | milliseconds value, to get accurate ms values you need to set interval to a smaller value example: 20ms |\n| seconds | number | seconds value |\n| minutes | number | minutes value |\n| hours | number | hours value |\n| days | number | days value |\n| totalSeconds | number | total number of seconds left in timer NOT converted to minutes, hours or days |\n| totalMilliseconds | number | total number of milliseconds left in timer NOT converted to minutes, hours or days |\n| isRunning | boolean | flag to indicate if timer is running or not |\n| pause | function | function to be called to pause timer |\n| start | function | function if called after pause the timer will continue based on original expiryTimestamp |\n| resume | function | function if called after pause the timer will continue countdown from last paused state |\n| restart | function | function to restart timer with new expiryTimestamp, accept 2 arguments first is the new `expiryTimestamp` of type Date object and second is `autoStart` of type boolean to decide if it should automatically start after restart or not, default is `true` |\n\n\n---\n\n## `useStopwatch` - [Demo](https://amrlabib.github.io/react-timer-hook/)\n\n### Example\n\n```javascript\nimport React from 'react';\nimport { useStopwatch } from 'react-timer-hook';\n\nfunction MyStopwatch() {\n  const {\n    totalSeconds,\n    milliseconds,\n    seconds,\n    minutes,\n    hours,\n    days,\n    isRunning,\n    start,\n    pause,\n    reset,\n  } = useStopwatch({ autoStart: true, interval: 20 });\n\n\n  return (\n    \u003cdiv style={{textAlign: 'center'}}\u003e\n      \u003ch1\u003ereact-timer-hook\u003c/h1\u003e\n      \u003cp\u003eStopwatch Demo\u003c/p\u003e\n      \u003cdiv style={{fontSize: '100px'}}\u003e\n        \u003cspan\u003e{days}\u003c/span\u003e:\u003cspan\u003e{hours}\u003c/span\u003e:\u003cspan\u003e{minutes}\u003c/span\u003e:\u003cspan\u003e{seconds}\u003c/span\u003e:\u003cspan\u003e{milliseconds}\u003c/span\u003e\n      \u003c/div\u003e\n      \u003cp\u003e{isRunning ? 'Running' : 'Not running'}\u003c/p\u003e\n      \u003cbutton onClick={start}\u003eStart\u003c/button\u003e\n      \u003cbutton onClick={pause}\u003ePause\u003c/button\u003e\n      \u003cbutton onClick={reset}\u003eReset\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default function App() {\n  return (\n    \u003cdiv\u003e\n      \u003cMyStopwatch /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n### Settings\n\n| key | Type | Required | Description |\n| --- | --- | --- | ---- |\n| autoStart | boolean | No | if set to `true` stopwatch will auto start, by default it is set to `false` |\n| offsetTimestamp | Date object | No | this will define the initial stopwatch offset example: `const stopwatchOffset = new Date(); stopwatchOffset.setSeconds(stopwatchOffset.getSeconds() + 300);` this will result in a 5 minutes offset and stopwatch will start from 0:0:5:0 instead of 0:0:0:0 |\n| interval | number | No | value to change the interval of the stopwatch, by default it is set to 1000ms. Note: this value will not affect the stopwatch, it will just define the frequency used to calculate the current timer values. For example, if you have a use case where milliseconds are used, you need to use a smaller value for the interval, for example, 20ms or 100ms based on your needs. |\n\n### Values\n\n| key | Type | Description |\n| --- | --- | ---- |\n| milliseconds | number | milliseconds value, to get accurate ms values you need to set interval to a smaller value example: 20ms |\n| seconds | number | seconds value |\n| minutes | number | minutes value |\n| hours | number | hours value |\n| days | number | days value |\n| totalSeconds | number | total number of seconds in stopwatch NOT converted to minutes, hours or days |\n| isRunning | boolean | flag to indicate if stopwatch is running or not |\n| start | function | function to be called to start/resume stopwatch |\n| pause | function | function to be called to pause stopwatch |\n| reset | function | function to be called to reset stopwatch to 0:0:0:0, you can also pass offset parameter to this function to reset stopwatch with offset, similar to how `offsetTimestamp` will offset the initial stopwatch time, this function will accept also a second argument which will decide if stopwatch should automatically start after reset or not default is `true` |\n\n\n---\n\n\n## `useTime` - [Demo](https://amrlabib.github.io/react-timer-hook/)\n\n### Example\n\n```javascript\nimport React from 'react';\nimport { useTime } from 'react-timer-hook';\n\nfunction MyTime() {\n  const {\n    milliseconds,\n    seconds,\n    minutes,\n    hours,\n    ampm,\n  } = useTime({ format: '12-hour', interval: 20 });\n\n  return (\n    \u003cdiv style={{textAlign: 'center'}}\u003e\n      \u003ch1\u003ereact-timer-hook \u003c/h1\u003e\n      \u003cp\u003eCurrent Time Demo\u003c/p\u003e\n      \u003cdiv style={{fontSize: '100px'}}\u003e\n        \u003cspan\u003e{hours}\u003c/span\u003e:\u003cspan\u003e{minutes}\u003c/span\u003e:\u003cspan\u003e{seconds}\u003c/span\u003e\u003cspan\u003e{milliseconds}\u003c/span\u003e\u003cspan\u003e{ampm}\u003c/span\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default function App() {\n  return (\n    \u003cdiv\u003e\n      \u003cMyTime /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n### Settings\n\n| key | Type | Required | Description |\n| --- | --- | --- | ---- |\n| format | string | No | if set to `12-hour` time will be formatted with am/pm |\n| interval | number | No | value to change the interval of the time, by default it is set to 1000ms. Note: this value will not affect the thime, it will just define the frequency used to calculate the current time values. For example, if you have a use case where milliseconds are used, you need to use a smaller value for the interval, for example, 20ms or 100ms based on your needs. |\n\n### Values\n\n| key | Type | Description |\n| --- | --- | ---- |\n| milliseconds | number | milliseconds value |\n| seconds | number | seconds value |\n| minutes | number | minutes value |\n| hours | number | hours value |\n| ampm | string | am/pm value if `12-hour` format is used |\n\n\n---\n\n### Deprecation Warning:\n\nStarting from `v1.1.0` and above default export `useTimer` is deprecated, your old code will still work but it is better to start using named exports `{ useTimer, useStopwatch, useTime }`\n","funding_links":[],"categories":["React"],"sub_categories":["React Components"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famrlabib%2Freact-timer-hook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famrlabib%2Freact-timer-hook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famrlabib%2Freact-timer-hook/lists"}