Latest Socket ResearchMalicious Chrome Extension Performs Hidden Affiliate Hijacking.Details
Socket
Book a DemoInstallSign in
Socket

react-native-swipeable-actions

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-swipeable-actions

High-performance native swipeable row component for React Native using Expo Modules

latest
Source
npmnpm
Version
0.1.2
Version published
Maintainers
1
Created
Source

react-native-swipeable-actions

A high-performance native swipeable row component for React Native. Native alternative to react-native-gesture-handler/Swipeable - no react-native-reanimated required.

Features

  • Pure native gestures - no JS thread blocking
  • 60fps spring animations on both iOS and Android
  • No react-native-reanimated dependency
  • Built-in FlashList/virtualized list support via recyclingKey
  • AutoClose pattern for chat-style swipe-to-reply
  • Lazy action rendering for optimal performance

Performance

Benchmark comparison on Android 16, Pixel 8 Pro, GrapheneOS — List Demo with 100 items:

react-native-gesture-handler/Swipeablereact-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

ReanimatedPure 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

Installation

npm install react-native-swipeable-actions

Peer Dependencies

{
  "expo": ">=50.0.0",
  "expo-modules-core": ">=1.0.0",
  "react": ">=18.0.0",
  "react-native": ">=0.73.0"
}

Basic Usage

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>
  )
}

Props

PropTypeDefaultDescription
childrenReactNoderequiredRow content
actionsReactNoderequiredAction buttons revealed on swipe
actionsWidthnumberrequiredWidth of actions container in pixels
actionsPosition'left' | 'right''right'Position of actions ('left' = swipe right to reveal)
frictionnumber1Drag damping factor (0-1). Lower = more resistance
thresholdnumber0.4Snap-to threshold as percentage of actionsWidth (0-1)
dragOffsetFromEdgenumber0Minimum drag distance before gesture starts
autoClosebooleanfalseAuto-close after swipe release (for swipe-to-reply)
autoCloseTimeoutnumber0Delay in ms before auto-closing
recyclingKeystring | number-Unique key for FlashList/recycling support
styleStyleProp<ViewStyle>-Container style
testIDstring-Test ID for e2e testing

Callbacks

CallbackTypeDescription
onSwipeStart() => voidCalled when swipe gesture begins
onSwipeStateChange(state: 'open' | 'closed') => voidCalled when gesture ends (before animation)
onSwipeEnd(state: 'open' | 'closed') => voidCalled when animation completes
onProgress(progress: number) => voidCalled on each frame (0 = closed, 1 = fully open)

Ref Methods

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()

Static Methods

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

AutoClose Pattern (Swipe-to-Reply)

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>

FlashList Integration

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}
    />
  )
}

Architecture

┌─────────────────────────────────────────────────────────────┐
│  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:

  • Gestures handled entirely in native code for 60fps performance
  • Actions rendered lazily on first swipe gesture (performance optimization)
  • Recycling key enables state persistence in virtualized lists
  • No SharedValue dependency - progress synced via native events

Platform Support

PlatformVersion
iOS12.0+
AndroidAPI 21+

TypeScript

Full TypeScript support with exported types:

import {
  Swipeable,
  SwipeableProps,
  SwipeableMethods,
  SwipeableStatic,
  SwipeProgressEvent,
  SwipeStateEvent,
} from 'react-native-swipeable-actions'

Testing

Jest mock is included for testing components that use Swipeable:

// jest.config.js
import 'react-native-swipeable-actions/jestSetup.js'

License

MIT

Keywords

react-native

FAQs

Package last updated on 02 Jan 2026

Did you know?

Socket

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.

Install

Related posts