From 058addc7636640b8bfcc7cd9e59a3606381f85ae Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 19 Feb 2026 05:02:06 -0500 Subject: [PATCH 01/15] Fix GestureDetector unresponsive after display:none toggle (New Arch) (#3964) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On New Architecture, when a parent view has display: 'none' and siblings change while hidden, the native UIView backing a component may be recycled and replaced. The React view tag stays the same but the UIView instance changes, causing gesture recognizers to be lost. This adds a reattachHandlersIfNeeded check in flushOperations that re-binds handlers whose native view has changed. The check is a fast no-op (pointer comparison) when views haven't been recycled. Fixes #3937 Tested with both v2 (Gesture.Tap()) and v3 (useTapGesture) APIs on iOS simulator (New Architecture). Minimal repro to verify the fix: ```ts import React, { useCallback, useState } from 'react'; import { Button, StyleSheet, Text, View } from 'react-native'; import { Gesture, GestureDetector, useTapGesture, } from 'react-native-gesture-handler'; export default function DisplayNone() { const [tapCountV2, setTapCountV2] = useState(0); const [tapCountV3, setTapCountV3] = useState(0); const tapV2 = Gesture.Tap() .runOnJS(true) .onStart(() => { setTapCountV2((c) => c + 1); }); const tapV3 = useTapGesture({ runOnJS: true, onActivate: () => { setTapCountV3((c) => c + 1); }, }); const [visible, setVisible] = useState(true); const [randomViews, setRandomViews] = useState(100); const runTest = useCallback(() => { setVisible(false); setTimeout(() => { setRandomViews(Math.random() * 100); setTimeout(() => { setVisible(true); }, 500); }, 500); }, []); return ( 0 ? 'green' : 'red', fontSize: 24 }, ]}> v2 Tap count: {tapCountV2} 0 ? 'green' : 'red', fontSize: 24 }, ]}> v3 Tap count: {tapCountV3}