npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-yet-another-stopwatch-timer

v1.0.1

Published

Highly extensible stopwatch, timer, counter component for React Native

Readme

react-native-yet-another-stopwatch-timer

Dynamic JSON Badge Dynamic JSON Badge Dynamic JSON Badge Dynamic JSON Badge

Features

A fully extensible stopwatch, timer component for React Native.

Installation

npm install --save react-native-yet-another-stopwatch-timer

This library uses react-native-reanimated and react-native-worklets listed as peer dependencies so you have to provide them if your project does not already use them:

npm install --save react-native-reanimated react-native-worklets

Yes, since v7 npm install automatically installs peerDependencies, however I got 'react-native-worklets doesn't seem to be initialized' error loop in a fresh project until installed peerDependencies manually.

Add react-native-worklets plugin to your babel.config.js as stated in reanimated installation guide.

Minimal supported versions of peer dependencies are defined by react-native-reanimated compatibility table and react-native-worklets compatibility table.

Usage

Check out example project for most of use cases:

| File | Example description | | :---- | :----------- | | Stopwatch | controlling the stopwatch, providing style for digits, callback after every transition | | Timer | controlling the timer, setting initial value for countdown, providing style for digits, callback after every transition | | Derived | controlling the timer, setting initial value for countdown, providing style for digits, custom render function | | Intervals | controlling the stopwatch, providing style for digits, using counter value in handler, using callback after transition success, using Static renderer for other component to preserve same style |

Or check minimal examples to copy-paste:

Minimal Stopwatch example

import React, { useRef, useCallback } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import { Stopwatch, StopwatchTransitions } from 'react-native-yet-another-stopwatch-timer';

const Component = () => {
  const timerRef = useRef(null);
  // use timerRef to call transitionTo property to switch states
  const run = useCallback(() => timerRef.current?.transitionTo({ name: StopwatchTransitions.Run }), [ timerRef ]);
  // use onBeforeTransition, onAfterTransition callback to access counter on state change
  const pause = useCallback(() => timerRef.current?.transitionTo({ name: StopwatchTransitions.Pause, onAfterTransition: console.log }), [ timerRef ]);
  return (
    <View style={{ flex: 1 }}>
      <TouchableOpacity onPress={run}><Text>Run</Text></TouchableOpacity>
      <TouchableOpacity onPress={pause}><Text>Pause</Text></TouchableOpacity>
      <Stopwatch timerRef={timerRef} />
    </View>
  );
};

Minimal Timer usage example

import React, { useState, useRef, useCallback } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import { Timer, TimerTransitions, TimerStates } from 'react-native-yet-another-stopwatch-timer';

const Component = ({ initialCounterValue = 5000 }) => {
  const [ laps, setLaps ] = useState(0);
  const timerRef = useRef(null);
  // use timerRef to call transitionTo property to switch states, set transition name to one of StopwatchTransitions, counterValue if you want to change it outside of timingHandler
  const run = useCallback(() => timerRef.current?.transitionTo({ name: TimerTransitions.Run, counterValue: initialCounterValue }), [ timerRef, initialCounterValue ]);
  const onAfterTransition = useCallback((_, { name }, { nextState }) => {
    if (name === TimerTransitions.Stop && nextState === TimerStates.Stopped) setLaps((prevLaps) => prevLaps + 1);
  }, [ setLaps ]);
  return (
    <View style={{ flex: 1 }}>
      <TouchableOpacity onPress={run}><Text>Run</Text></TouchableOpacity>
      <Timer timerRef={timerRef} onAfterTransition={onAfterTransition} initialCounterValue={initialCounterValue} />
      <Text>Laps: {laps}</Text>
    </View>
  );
};

API

Autogenerated documentation is here.

Q&A

How to show less or more places? How to render differently, use other digit changing animations?

Provide your own render property and declare needed reanimated derived values for counter, that gets updated by timingHandler each timingInterval by timingInterval, by default counter gets incremented by 100 every 100 ms. Check example Derived.

How to get better timing precision?

setTimeout and setInterval guarantee that callback will be called not sooner than timeout ms. For precise timing you can either implement a self adjusting timer, that compensates for varying timeout call times, or use Date.now(), or if you just need to accurately capture when run, pause or stop events occur, capture precise time in global onBeforeTransition/onAfterTransition handlers, or for individual transitions in transitionHandler.

Getting started with customisation

The module exports Counter, Stopwatch and Timer components, state and transition names.

Counter serves as base component that only provides means of calling transition function and registers timing handler.

Stopwatch is implemented by providing default values for Counter:

  • initialState for the state machine
  • timingHandler to increment the counter at least every timingInterval by timingInterval
  • removeTiming to clean the timeout when the component is removed
  • transitionHandler that returns an object with nextState property based on transition and current state
  • render function that returns a React component provided counter and style arguments

Timer features are achieved by providing other timing function to Stopwatch that decrements the counter and issues a transition to stopped state when it reaches zero.

Development

In order to develop the application or build android .apk from the sources one should:

  1. Clone this repository
  2. Navigate to parent directory and install dev dependencies with npm ci for linting npm run lint and typescript typechecking npm run typecheck.
  3. Navigate to example folder: cd example
  4. Install example project dependencies npm ci, since library has only peer dependencies
  5. Run Metro bundler with npm run start
  6. Connect physical device or an emulator via adb, like this (tested with mEMU):
    • adb connect 127.0.0.1:21503
    • adb reverse tcp:8081 tcp:8081
  7. Build and watch with npm run-android, changes from src directory are picked automatically because of example metro and babel configurations.

Note: example project is configured in a way, that may cause issues if you save anything as a regular dependency in parent library

Contributions

PR are always welcome!