react-native-safe-press
v0.1.0
Published
A lightweight React Native library to prevent double taps, rapid presses, and duplicate actions.Simple, configurable protection against duplicate presses in React Native.
Downloads
131
Readme
react-native-safe-press
One hook. Zero duplicate presses.
react-native-safe-press is a tiny, dependency-free React Native utility that prevents accidental duplicate presses.
- Tiny: <2 KB minified
- Zero dependencies: Pure React hook
- Fully typed: Written in TypeScript
- Compatible: Works seamlessly with Expo, React Native, and React Native Web
1. Why?
Accidental double-taps on buttons can cause duplicate api requests, multiple form submissions, or erratic screen navigation.
Without react-native-safe-press
Double Tap → [Button] → POST /login
→ POST /login ❌ (Fires twice)With react-native-safe-press
Double Tap → [Button] → POST /login ✅ (Only fires once)2. Installation
npm install react-native-safe-press
# or
yarn add react-native-safe-press3. Quick Start
Protect your buttons in 30 seconds:
import React from 'react';
import { Button } from 'react-native';
import { useSafePress } from 'react-native-safe-press';
export function LoginButton() {
const { onPress, isLocked } = useSafePress(async () => {
await login();
});
return (
<Button
title={isLocked ? "Logging in..." : "Login"}
disabled={isLocked}
onPress={onPress}
/>
);
}4. API
const { onPress, isLocked } = useSafePress(callback, options);Options
| Option | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| duration | number | 1000 | Lock duration in milliseconds after the callback finishes or promise settles. |
Return Value
| Property | Type | Description |
| :--- | :--- | :--- |
| onPress | (...args: Parameters<T>) => void | The wrapped function to pass to your button's onPress prop. |
| isLocked | boolean | Reactive state indicating if the press handler is currently locked. |
5. How It Works
Synchronous Callback
Tap
│
▼
Lock (isLocked = true)
│
▼
Execute callback
│
▼
Wait duration (e.g. 1000ms)
│
▼
Unlock (isLocked = false)Asynchronous Callback
Tap
│
▼
Lock (isLocked = true)
│
▼
Await Promise resolution / rejection
│
▼
Wait duration (e.g. 1000ms)
│
▼
Unlock (isLocked = false)During the lock period, any additional taps are silently ignored.
6. FAQ
Does it work with async callbacks?
Yes! If your callback returns a Promise, the hook will automatically await it and keep isLocked = true until the promise settles, then wait the additional duration before unlocking.
What React Native components does it support?
It works with any component that accepts an onPress callback:
✓ Button✓ Pressable✓ TouchableOpacity✓ TouchableHighlight✓ TouchableWithoutFeedback✓ React Native Gesture Handler components✓ Custom button components
What happens if the promise never resolves?
If the promise hangs indefinitely, the hook will remain locked. This is by design to ensure duplicate presses are never fired while an action is still pending.
Does it swallow promise rejections?
No. Rejections cascade naturally and can be caught inside your callback, but the hook will still safely unlock the press state when the promise rejects.
License
MIT
Made with create-react-native-library
