Skip to content

Commit 3ad1fcc

Browse files
authored
Fix memory leak in ReanimatedSwipeable on programmatic close (#3790)
# Fix memory leak in ReanimatedSwipeable on programmatic close ## Problem ReanimatedSwipeable experiences a performance leak when closing programmatically via `.close()` or triggered by child content interaction. The UI thread produces infinite updates even after the spring animation visually finishes. ### Symptoms - Infinite UI thread updates when calling `.close()` programmatically - Animation appears complete but background processing continues indefinitely - Issue only occurs with programmatic closure, not manual swipe gestures - Affects iOS with react-native 0.81.0+ and gesture-handler 2.29.0 ## Root Cause The `animateRow` function accepts an optional `velocityX` parameter: ```typescript const animateRow = (toValue: number, velocityX?: number) => { ``` When closing programmatically, no velocity value is provided, resulting in velocityX = undefined. The spring animation configuration requires numeric velocity values to: 1. Calculate motion trajectory - how the value changes over time 2. Detect convergence - when animation should stop based on restSpeedThreshold and restDisplacementThreshold With undefined velocity: - Spring cannot properly evaluate convergence conditions - Animation loop never detects it should terminate - UI thread continues updating indefinitely Manual swipes work fine because gesture handlers provide actual velocity values (e.g., -300, 150), ensuring valid numeric input. Solution Set a default parameter value for velocityX: ```typescript const animateRow = (toValue: number, velocityX = 0) => { ``` This ensures: - velocityX is always a number, never undefined - Spring animation receives valid initial velocity of 0 (no momentum) - Convergence detection works correctly - animation stops when position settles - Single point of fix at function signature level (cleaner than multiple nullish coalescing checks) Testing - Programmatic .close() no longer causes infinite updates - Manual swipe gestures continue to work correctly - Animation behavior remains unchanged visually Video from the same repo: https://youtu.be/qqS_ZfSU7NI
1 parent 7cfe2fc commit 3ad1fcc

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ const Swipeable = (props: SwipeableProps) => {
203203
);
204204

205205
const animateRow: (toValue: number, velocityX?: number) => void = useCallback(
206-
(toValue: number, velocityX?: number) => {
206+
(toValue: number, velocityX = 0) => {
207207
'worklet';
208208

209209
const translationSpringConfig = {

0 commit comments

Comments
 (0)