
Security News
Inside Lodash’s Security Reset and Maintenance Reboot
Lodash 4.17.23 marks a security reset, with maintainers rebuilding governance and infrastructure to support long-term, sustainable maintenance.
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
Lodash 4.17.23 marks a security reset, with maintainers rebuilding governance and infrastructure to support long-term, sustainable maintenance.

Security News
n8n led JavaScript Rising Stars 2025 by a wide margin, with workflow platforms seeing the largest growth across categories.

Security News
The U.S. government is rolling back software supply chain mandates, shifting from mandatory SBOMs and attestations to a risk-based approach.