
Security News
AI Agent Lands PRs in Major OSS Projects, Targets Maintainers via Cold Outreach
An AI agent is merging PRs into major OSS projects and cold-emailing maintainers to drum up more work.
react-native-swipeable-actions
Advanced tools
High-performance native swipeable row component for React Native using Expo Modules
A high-performance native swipeable row component for React Native. Native alternative to react-native-gesture-handler/Swipeable - no react-native-reanimated required.
react-native-reanimated dependencyrecyclingKeyBenchmark comparison on Android 16, Pixel 8 Pro, GrapheneOS — List Demo with 100 items:
| react-native-gesture-handler/Swipeable | react-native-swipeable-actions |
|---|---|
|
https://github.com/user-attachments/assets/6d7cf1e6-c719-4044-8b47-205e94a38d10 |
https://github.com/user-attachments/assets/f59ef788-caf4-4985-93bc-8d098122fe1a |
| Reanimated | Pure native |
| Avg 60.9 FPS (Min: 56.7 / Max: 65.7) | Avg 116.8 FPS (Min: 109.9 / Max: 120.3) |
Videos not loading? View on GitHub
npm install react-native-swipeable-actions
{
"expo": ">=50.0.0",
"expo-modules-core": ">=1.0.0",
"react": ">=18.0.0",
"react-native": ">=0.73.0"
}
import { Swipeable, SwipeableMethods } from 'react-native-swipeable-actions'
import { useRef } from 'react'
import { View, Text, TouchableOpacity } from 'react-native'
function DeleteAction({ onPress }: { onPress: () => void }) {
return (
<TouchableOpacity onPress={onPress} style={styles.deleteAction}>
<Text style={styles.actionText}>Delete</Text>
</TouchableOpacity>
)
}
function MyRow() {
const swipeableRef = useRef<SwipeableMethods>(null)
return (
<Swipeable
ref={swipeableRef}
actions={<DeleteAction onPress={() => console.log('Delete!')} />}
actionsWidth={80}
onSwipeEnd={(state) => console.log('Swipe ended:', state)}
>
<View style={styles.row}>
<Text>Swipe me left</Text>
</View>
</Swipeable>
)
}
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | required | Row content |
actions | ReactNode | required | Action buttons revealed on swipe |
actionsWidth | number | required | Width of actions container in pixels |
actionsPosition | 'left' | 'right' | 'right' | Position of actions ('left' = swipe right to reveal) |
friction | number | 1 | Drag damping factor (0-1). Lower = more resistance |
threshold | number | 0.4 | Snap-to threshold as percentage of actionsWidth (0-1) |
dragOffsetFromEdge | number | 0 | Minimum drag distance before gesture starts |
autoClose | boolean | false | Auto-close after swipe release (for swipe-to-reply) |
autoCloseTimeout | number | 0 | Delay in ms before auto-closing |
recyclingKey | string | number | - | Unique key for FlashList/recycling support |
style | StyleProp<ViewStyle> | - | Container style |
testID | string | - | Test ID for e2e testing |
| Callback | Type | Description |
|---|---|---|
onSwipeStart | () => void | Called when swipe gesture begins |
onSwipeStateChange | (state: 'open' | 'closed') => void | Called when gesture ends (before animation) |
onSwipeEnd | (state: 'open' | 'closed') => void | Called when animation completes |
onProgress | (progress: number) => void | Called on each frame (0 = closed, 1 = fully open) |
Access via ref:
const swipeableRef = useRef<SwipeableMethods>(null)
// Close the row (with optional animation)
swipeableRef.current?.close() // animated
swipeableRef.current?.close(false) // instant
// Open the row
swipeableRef.current?.open()
Control swipeables globally by their recyclingKey:
import { Swipeable } from 'react-native-swipeable-actions'
// Open a specific row
Swipeable.open('row-1')
// Close a specific row
Swipeable.close('row-1') // animated
Swipeable.close('row-1', false) // instant
// Close all open rows
Swipeable.closeAll() // animated
Swipeable.closeAll(false) // instant
For chat-style swipe-to-reply where the row should automatically close:
<Swipeable
actions={<ReplyIndicator />}
actionsWidth={60}
actionsPosition="right"
autoClose={true}
threshold={0.6}
onSwipeEnd={(state) => {
if (state === 'open') {
// Trigger reply action
onReply(message)
}
}}
>
<ChatMessage message={message} />
</Swipeable>
For virtualized lists, use recyclingKey to persist swipe state across recycling:
import { FlashList } from '@shopify/flash-list'
function MessageList({ messages }) {
return (
<FlashList
data={messages}
renderItem={({ item }) => (
<Swipeable
recyclingKey={item.id}
actions={<DeleteAction />}
actionsWidth={80}
>
<MessageRow message={item} />
</Swipeable>
)}
estimatedItemSize={60}
/>
)
}
┌─────────────────────────────────────────────────────────────┐
│ JS Layer (React) │
│ ┌─────────────────┐ ┌──────────────────────────────────┐ │
│ │ <Swipeable> │ │ Actions (ReactNode) │ │
│ │ - renderActions│──│ - Rendered lazily on first swipe│ │
│ │ - ref methods │ │ - Any React components │ │
│ └────────┬────────┘ └──────────────────────────────────┘ │
└───────────│─────────────────────────────────────────────────┘
│ Expo Modules Bridge
┌───────────▼─────────────────────────────────────────────────┐
│ Native Layer (Kotlin/Swift) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ SwipeableView ││
│ │ - UIPanGestureRecognizer (iOS) / OnTouchListener (And) ││
│ │ - Spring animations (UIView.animate / DynamicAnimation)││
│ │ - Progress events @ 60fps (CADisplayLink / Choreograph)││
│ │ - LRU cache for recycling state persistence ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Key design decisions:
| Platform | Version |
|---|---|
| iOS | 12.0+ |
| Android | API 21+ |
Full TypeScript support with exported types:
import {
Swipeable,
SwipeableProps,
SwipeableMethods,
SwipeableStatic,
SwipeProgressEvent,
SwipeStateEvent,
} from 'react-native-swipeable-actions'
Jest mock is included for testing components that use Swipeable:
// jest.config.js
import 'react-native-swipeable-actions/jestSetup.js'
MIT
FAQs
High-performance native swipeable row component for React Native using Expo Modules
We found that react-native-swipeable-actions demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
An AI agent is merging PRs into major OSS projects and cold-emailing maintainers to drum up more work.

Research
/Security News
Chrome extension CL Suite by @CLMasters neutralizes 2FA for Facebook and Meta Business accounts while exfiltrating Business Manager contact and analytics data.

Security News
After Matplotlib rejected an AI-written PR, the agent fired back with a blog post, igniting debate over AI contributions and maintainer burden.