@alimirzayev/react-native-background-timer
v0.1.0
Published
Reliable lifecycle-aware timers for modern React Native and Expo development builds
Downloads
206
Maintainers
Readme
@alimirzayev/react-native-background-timer
Modern background-aware timers for the React Native New Architecture
Built from scratch with TurboModules + Codegen, first-class TypeScript, real native cancellation, Expo development builds, and a safe web fallback.
Getting started · Why this package? · API · Platform behavior · Migration
[!IMPORTANT] This is a modern, clean implementation - not a fork of the original package. It is designed for current React Native projects and explicitly documents what mobile operating systems can and cannot guarantee.
At a glance
- New Architecture first - typed TurboModule spec, Codegen events, Hermes-ready.
- Expo-ready - works in Expo development builds through standard autolinking; no config plugin required.
- Correct cancellation - clearing a timer removes both its JavaScript callback and native scheduled work.
- Multiple timers - independent timeouts and intervals with one shared native event subscription.
- Stable cadence - monotonic Android deadlines skip missed ticks instead of creating callback storms.
- Lifecycle-safe - native timers, listeners, background assertions, and WakeLocks are cleaned up.
- TypeScript included - no separate
@typespackage. - Web-safe - the same API works through a foreground-only JavaScript fallback.
- Tested release path - CI, coverage thresholds, native lint/tests, and a publish-blocking verification step.
Why this package?
The original react-native-background-timer was created for the legacy React Native bridge. This package preserves the familiar timer experience while rebuilding the native and JavaScript layers around the current React Native architecture.
| Area | Legacy approach | This package |
| ------------------- | ---------------------------------------- | -------------------------------------------- |
| Native architecture | Legacy bridge module | TurboModule + Codegen |
| Events | Manual NativeEventEmitter wiring | Typed Codegen events |
| TypeScript | External/community definitions | Built in |
| Cancellation | Reported timeout/interval cleanup issues | JS and native work cancelled together |
| Concurrent timers | Historically inconsistent APIs | Independent timers by design |
| Long-running IDs | Callback object growth / range reports | Map storage and safe ID recycling |
| Timing cadence | Repeating delay accumulation | Monotonic deadlines and missed-tick skipping |
| Expo | Legacy eject-oriented setup | Expo development builds + autolinking |
| Web | No dependable package fallback | Foreground-compatible web driver |
| Verification | No current regression suite | Jest, Android unit/lint, host builds, CI |
Issue classes addressed
The implementation includes targeted regressions for common reports from the original library:
- New Architecture and builds:
#536,#532,#530,#527,#526,#367,#290,#242 - Immediate, long-running, and synchronized timers:
#533,#529,#270,#271,#256,#299 - Cancellation and multiple timers:
#524,#337,#310,#366 - Safe missing-native-module behavior:
#531 - React Native Web fallback:
#455 - iOS reload cleanup protections:
#460(device stress loop remains pending)
See the issue regression matrix for test details. OS-controlled behavior such as iOS suspension, Android Doze, OEM process killing, or force-quit is documented as a limitation - not presented as a library fix.
Compatibility
| Target | Support |
| ------------ | --------------------------------------------------------------- |
| React Native | Verified on 0.82.1, 0.83.10, 0.84.1, 0.85.3, and 0.86 |
| React | >=19.1 |
| Architecture | New Architecture / TurboModules |
| Expo | SDK 57 development builds verified; Expo Go is not supported |
| Android | API 24+, compile SDK 36 |
| iOS | 16.4+ |
| Web | Expo Web / React Native Web foreground fallback |
[!NOTE] React Native 0.82.1 passes Android normally. With Xcode 26.5, its bundled
fmt 11.0.2pod must be compiled as C++17 due to an upstream toolchain incompatibility. This does not originate in this package and is not required for React Native 0.83+.
Getting started
Install
npm install @alimirzayev/react-native-background-timeryarn add @alimirzayev/react-native-background-timerBare React Native
Android uses standard autolinking. For iOS, install pods after adding the package:
cd ios && pod installRebuild the native application after installation.
Expo
This package contains native code, so use an Expo development build:
npx expo install @alimirzayev/react-native-background-timer
npx expo run:android
# or
npx expo run:ios[!WARNING] Expo Go is not supported. Package import is safe, but starting a native timer without a development build throws an actionable error.
Quick start
import BackgroundTimer from "@alimirzayev/react-native-background-timer";
const timerId = BackgroundTimer.setInterval(
() => {
console.log("tick");
},
1_000,
{ immediate: true },
);
// Later: removes the callback and native timer.
BackgroundTimer.clearInterval(timerId);Timeout
const timeoutId = BackgroundTimer.setTimeout(() => {
console.log("finished");
}, 2_000);
BackgroundTimer.clearTimeout(timeoutId);Handle iOS background-time expiration
const unsubscribe = BackgroundTimer.addBackgroundTimeExpiredListener(() => {
// Save state and stop background work gracefully.
console.log("iOS background time expired");
});
unsubscribe();Inspect platform capabilities
const capabilities = BackgroundTimer.getCapabilities();
console.log(capabilities.backgroundExecution);
// Android: "best-effort"
// iOS: "time-limited"
// Web: "none"API
| Method | Returns | Description |
| ----------------------------------------------- | ------------------- | --------------------------------------- |
| setTimeout(callback, delay?) | TimerId | Schedule one callback |
| clearTimeout(id) | void | Cancel one timeout |
| setInterval(callback, delay?, options?) | TimerId | Schedule a repeating callback |
| clearInterval(id) | void | Cancel one interval |
| clearAllTimers() | void | Cancel all timers owned by this package |
| addBackgroundTimeExpiredListener(listener) | unsubscribe | Observe iOS expiration |
| getCapabilities() | TimerCapabilities | Inspect runtime guarantees |
| runBackgroundTimer(callback, delay, options?) | TimerId | Single-timer migration helper |
| stopBackgroundTimer() | void | Stop the migration-helper timer |
options.immediate fires an interval once immediately, then continues at the requested delay. Delays must be finite values from 0 through 2,147,483,647 milliseconds; repeating intervals use a minimum of 1 millisecond.
The full API contract is documented in API.md.
Platform behavior
Android
- Schedules native timers from monotonic deadlines.
- Supports independent one-shot and repeating timers.
- Holds a partial WakeLock only while the host is backgrounded and active timers remain.
- Releases callbacks and WakeLock state on clear, resume, host destruction, or module invalidation.
- Skips missed ticks instead of replaying a callback storm.
Android execution is best effort. Doze, force-stop, OEM battery policies, or process pressure can stop the app. Continuous user-visible work belongs in a foreground service with a visible notification.
iOS
- Uses one GCD timer source per timer.
- Requests a UIKit background task when active timers enter the background.
- Coalesces missed repeating ticks.
- Emits an expiration event when iOS revokes background time.
- Ends timers and background assertions during clear, foregrounding, invalidation, and deallocation.
iOS background execution is time limited. After the granted time expires, iOS may suspend the app. No timer library can promise indefinite execution or execution after force-quit.
Web
- Automatically selects a JavaScript driver.
- Provides the same timeout, interval, cancellation, and capability APIs.
- Never claims native background execution.
Browsers can throttle or suspend timers in inactive tabs. Web support is API compatibility for foreground use.
Choose the right background tool
Use this package when you need second- or millisecond-level callbacks while the application process still has permission to execute.
| Requirement | Recommended tool | | -------------------------------------------- | --------------------------------------------------- | | Short, frequent callbacks while backgrounded | This package | | Deferrable sync or maintenance work | Expo BackgroundTask / WorkManager / BGTaskScheduler | | Alarm or user-visible event at a future time | Local notifications | | Continuous Android work | Foreground service | | Work after force-quit | OS-specific scheduling; not a timer |
For countdowns and stopwatches, store a timestamp and calculate elapsed time when the app resumes instead of depending on every tick.
Migration from react-native-background-timer
Change the import:
- import BackgroundTimer from 'react-native-background-timer';
+ import BackgroundTimer from '@alimirzayev/react-native-background-timer';Standard calls keep the familiar shape:
const id = BackgroundTimer.setInterval(callback, 1_000);
BackgroundTimer.clearInterval(id);For older code using a single global background timer:
BackgroundTimer.runBackgroundTimer(callback, 1_000);
BackgroundTimer.stopBackgroundTimer();The migration helpers intentionally own only one timer. Prefer the core timeout and interval API for new code.
Verification
- 38 Jest tests across timer engine, native driver, web driver, and issue regressions.
- 98.46% statements, 95.31% branches, 100% functions, 99.13% lines.
- Android native unit tests and lint pass.
- Bare React Native Android APK and iOS simulator application builds pass.
- Expo SDK 57 Android, iOS, and web host builds pass.
- Packaged
.tgzclean-install, autolinking, types, and Metro bundles pass. - CI enforces coverage and package verification.
prepublishOnlyblocks npm publication when verification fails.
Runnable examples:
Development
npm install
npm run verifyNative Android verification:
cd examples/bare/android
./gradlew \
:alimirzayev_react-native-background-timer:testDebugUnitTest \
:alimirzayev_react-native-background-timer:lintDebugLicense
MIT © Ali Mirzayev
