[Release] 2.32 Cherry-pick thread#4255
Merged
Merged
Conversation
- Remove the `getChildInDrawingOrderAtIndex` abstraction from `ViewConfigurationHelper` and its implementation in `RNViewConfigurationHelper` - Inline `viewGroup.getChildAt(i)` at the two call sites (`GestureHandlerOrchestrator` and `HoverGestureHandler`) - `ReactViewGroup.getZIndexMappedChildIndex` is a legacy architecture API that has been a no-op (returns its input unchanged) and has been removed in react/react-native#56717 ## Test plan - Android build via `cd apps/basic-example && yarn android`
React Native 0.86 removed `Libraries/Renderer/shims/ReactNative`, breaking the `RNRenderer` import. This PR switch to `RendererProxy` and fall back to the legacy shim for compatibility with RN < 0.86.
## Description
Discrete gestures on Android transition to `END` state before being
cancelled by other, higher priority gestures. Our current approach
missed case where gestures like `Tap` end in such transition (`5 -> 3`),
therefore `onFinalize` callback was never triggered.
## Test plan
<details>
<summary>Tested on the following code:</summary>
```tsx
import React from 'react';
import { StyleSheet, View } from 'react-native';
import {
GestureDetector,
useExclusiveGestures,
useTapGesture,
} from 'react-native-gesture-handler';
export default function EmptyExample() {
const t1 = useTapGesture({
onBegin: () => {
console.log('tap begin');
},
onActivate: () => {
console.log('tap activate');
},
onDeactivate: () => {
console.log('tap deactivate');
},
onFinalize: () => {
console.log('tap finalize');
},
});
const t2 = useTapGesture({
numberOfTaps: 2,
onBegin: () => {
console.log('double tap begin');
},
onActivate: () => {
console.log('double tap activate');
},
onDeactivate: () => {
console.log('double tap deactivate');
},
onFinalize: () => {
console.log('double tap finalize');
},
});
const g = useExclusiveGestures(t2, t1);
return (
<View style={styles.container}>
<GestureDetector gesture={g}>
<View style={styles.box} />
</GestureDetector>
</View>
);
}
const styles = StyleSheet.create({
box: {
width: 100,
height: 100,
backgroundColor: 'blue',
borderRadius: 10,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
```
</details>
Fixes #3435 Android includes the pointer being lifted in the `ACTION_POINTER_UP` event, so the event where the pointer is lifted is sent with `numberOfPointers = 2`. This PR changes that so the `numberOfPointers` is reported as `n - 1` for `ACTION_POINTER_UP` events. Note: The same applies to `ACTION_UP` and `ACTION_CANCEL` but I didn't include them to keep the behavior the same as on iOS. Reproducer from #3435
…aliases (#4232) ## Description Related: software-mansion/react-native-reanimated#9592 (same fix for `react-native-reanimated` and `react-native-worklets`) The pod script attempts to resolve `react-native/package.json` to get to the `version` and perform a version check. It however performs a redundant `react-native/../react-native` resolution i.e. it essentially performs `path.dirname(require.resolve('react-native/package.json'))` (correct), but then joins this with `${dir}/..`, then re-joins this with `react-native`. Re-entering the `react-native` directory can be invalid in case of symlinks in the `node_modules` structure. The easiest way to reproduce an issue is to use react-native-tvos's pattern of aliasing `"react-native": "npm:react-native-tvos@x.x.x"`. With isolated dependencies this will point a symlink at a directory that's named `react-native-tvos` and not `react-native`. The also applies to local `link:` dependency specifiers. Essentially, the directory name `react-native` is unnecessarily enforced. This would lead to a cryptic `file: no implicit conversion of nil into String.` error ## Test plan - Existing `pod install` in working projects should continue passing unchanged - https://github.com/kitten/douglowder--with-monorepo-tv-test/tree/init-pnpm - `pnpm i` then in `apps/tv` run `pnpm prebuild` (which runs `pod install`) --------- Co-authored-by: Michał Bert <63123542+m-bert@users.noreply.github.com>
## Description In ruby, functions and variables are global by design. In #4232 we dealt with it by changing name of exported function. However, the correct approach would be to keep our utils in separate module. This has also been introduced in [Reanimated](software-mansion/react-native-reanimated#9617). ## Test plan `pod install`
Fixes three issues: 1. `findGestureHandlerByRecognizer` was relying on `reactTag` to determine whether a view is managed by React Native. This is no longer set on the new architecture (we do it [here](https://github.com/software-mansion/react-native-gesture-handler/blob/e362f3a1ea2c04b78d3923c377dc2c62b23ca2d0/packages/react-native-gesture-handler/apple/RNGestureHandlerManager.mm#L206), this needs to be investigated). Instead, I changed it to check whether the view is a subclass of `RCTViewComponentView` which is a base for Fabric components. 2. `shouldHandleTouch` in the button component was converting the point to the wrong coordinate space when calling `wantsToHandleEventsAtPoint`. 3. `wantsToHandleEventsAtPoint` for api v3 was always trying to get the child of the view the gesture is attached to. Correct when gesture is attached to the detector, not when directly to view (virtual detector/`wantsToAttachDirectlyToView: YES`). Enable "Legacy examples" in the expo app and try to scroll, starting on one of the disabled buttons. |Before|After| |-|-| |<video src="https://github.com/user-attachments/assets/28cd0b95-85df-46e8-8ca4-28c042d725b0" />|<video src="https://github.com/user-attachments/assets/7116d3aa-557f-4828-9b4e-c0177ed89202" />| There's no pointer captured, but in the "before" video, I'm trying to scroll starting on `Nested buttons (sound & ripple)`.
For now it doesn't work with hook-based API 😞
<details>
<summary>Tested on the following code:</summary>
```tsx
import { useState } from 'react';
import { Pressable, StyleSheet, View } from 'react-native';
import {
Gesture,
GestureDetector,
GestureHandlerRootView,
RectButton,
useTapGesture,
} from 'react-native-gesture-handler';
const randomColor = () => {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return `rgb(${r},${g},${b})`;
};
export default function App() {
const [bgColor, setBgColor] = useState('black');
const tap = useTapGesture({
onDeactivate: () => {
setBgColor(randomColor());
},
disableReanimated: true,
});
const oldTap = Gesture.Tap()
.onEnd(() => {
setBgColor(randomColor());
})
.runOnJS(true);
return (
<GestureHandlerRootView style={styles.container}>
<View
style={{
width: 100,
height: 100,
borderRadius: 50,
backgroundColor: bgColor,
}}
/>
<View
style={[
styles.container,
{
width: '100%',
flexDirection: 'row',
},
]}>
<GestureDetector gesture={tap}>
<View style={styles.button} />
</GestureDetector>
<GestureDetector gesture={oldTap}>
<View style={styles.button} />
</GestureDetector>
<Pressable
style={styles.button}
onPress={() => {
setBgColor(randomColor());
}}
/>
<RectButton
style={styles.button}
onPress={() => {
setBgColor(randomColor());
}}
/>
</View>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-evenly',
alignItems: 'center',
},
button: {
width: 100,
height: 50,
backgroundColor: 'crimson',
borderRadius: 10,
},
});
```
</details>
This PR bumps Reanimated version, along with worklets. Since in `common-app` we still had Reanimated 3.18, I've also introduced necessary changes to types. Also, it turned out that our current setup cannot correctly resolve dependencies - I've updated `metro.config.js` to also block `common-app`, since this "app" only contains sources for examples and their `node_modules` shouldn't be used. Build and run example apps.
This PR bumps `expo` version in `expo-example` to 56. It also adds `yarn constraints` in order to keep Reanimated and Worklets in sync. Now running `yarn constraints --fix` will automatically set desired versions of packages in all `package.json` files across workspaces. Test example apps. > [!NOTE] > macOS is left far behind with React Native 0.81, so I guess it just waits for better time 😶
Contributor
There was a problem hiding this comment.
Pull request overview
Release-branch cherry-pick aggregation for react-native-gesture-handler 2.32, combining Android/iOS fixes and ecosystem upgrades (React Native 0.86, Expo 56, Reanimated/Worklets), plus example app and CI adjustments.
Changes:
- Update dependencies across workspaces (RN 0.86, Expo 56, Reanimated/Worklets) and add Yarn constraints config.
- iOS: adjust event dispatching behavior for RN 0.86/Fabric, fix duplicated
testID, and update recognizer/handler resolution logic. - Android: fix discrete gesture finalize edge case, pointer count reporting, and remove legacy child drawing-order helper.
Reviewed changes
Copilot reviewed 44 out of 49 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.config.cjs | Adds Yarn constraints to keep versions aligned across workspaces. |
| packages/react-native-gesture-handler/src/RNRenderer.web.ts | Removes web RNRenderer shim. |
| packages/react-native-gesture-handler/src/RNRenderer.ts | Removes RNRenderer shim import for RN < 0.86. |
| packages/react-native-gesture-handler/src/handlers/gestures/GestureDetector/utils.ts | Removes detector child validation logic and RNRenderer usage; import ordering tweak. |
| packages/react-native-gesture-handler/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts | Stops calling removed detector-children validator. |
| packages/react-native-gesture-handler/scripts/gesture_handler_utils.rb | Moves pod utils into a module and adjusts RN version detection. |
| packages/react-native-gesture-handler/RNGestureHandler.podspec | Uses the new Ruby module helper to compute RN minor version. |
| packages/react-native-gesture-handler/package.json | Bumps dev deps to RN 0.86 and adds Reanimated/Worklets dev deps. |
| packages/react-native-gesture-handler/jestSetup.js | Updates mocks formatting; adds GestureComponents + worklets mocks. |
| packages/react-native-gesture-handler/apple/RNGestureHandlerManager.mm | Updates NativeAnimated delivery path for RN 0.86+; removes direct-event helper. |
| packages/react-native-gesture-handler/apple/RNGestureHandlerButtonComponentView.mm | Clears wrapper accessibilityIdentifier to avoid duplicated testID matches (Detox). |
| packages/react-native-gesture-handler/apple/RNGestureHandlerButton.mm | Whitespace-only formatting changes. |
| packages/react-native-gesture-handler/apple/RNGestureHandler.mm | Updates dummy-handler lookup logic / coordinate-space-related behavior. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNViewConfigurationHelper.kt | Removes legacy drawing-order child helper method. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/ViewConfigurationHelper.kt | Removes drawing-order child helper API from interface. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt | Inlines getChildAt and removes static helper usage. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt | Updates state-change edge case comment; inlines getChildAt usage. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt | Fixes pointer count reported for ACTION_POINTER_UP. |
| package.json | Adds @yarnpkg/types dependency (for constraints typing/tooling). |
| apps/macos-example/tsconfig.json | Adds TS types reference and excludes Pods. |
| apps/macos-example/package.json | Bumps macOS example dependencies (RN macOS, Reanimated/Worklets, etc.) and Node engine. |
| apps/macos-example/metro.config.js | Updates exclusionList import path and blacklists both monorepo + common-app node_modules. |
| apps/macos-example/macos/Podfile | Enables new arch/Fabric and bumps macOS deployment target. |
| apps/macos-example/macos/MacOSExample.xcodeproj/project.pbxproj | Updates project settings, embeds frameworks phase, adjusts runpaths, enables Hermes. |
| apps/macos-example/macos/MacOSExample-macOS/Info.plist | Adds RCTNewArchEnabled key and formatting tweaks. |
| apps/macos-example/macos/MacOSExample-macOS/AppDelegate.mm | Sets RCTAppDependencyProvider for RN 0.86+ style app setup. |
| apps/macos-example/Gemfile.lock | Updates lockfile deps (Ruby stdlib gem extractions). |
| apps/macos-example/Gemfile | Adds gems needed for Ruby 3.4 stdlib removals. |
| apps/expo-example/package.json | Bumps Expo SDK and related deps; adds pager-view/worklets. |
| apps/expo-example/metro.config.js | Mirrors common-app node_modules blacklisting approach. |
| apps/common-app/src/release_tests/gesturizedPressable/delayedPressExample.tsx | Updates Reanimated spring config usage. |
| apps/common-app/src/release_tests/combo/index.tsx | Removes slider/native wrapper usage and related styles. |
| apps/common-app/src/new_api/manualGestures/index.tsx | Updates Reanimated SharedValue typings. |
| apps/common-app/src/new_api/drag_n_drop/Draggable.tsx | Updates Reanimated SharedValue typings. |
| apps/common-app/src/new_api/chat_heads/index.tsx | Updates Reanimated SharedValue typings. |
| apps/common-app/src/new_api/camera/AnimatedCameraView.tsx | Updates Reanimated typings and ref typing for animated camera component. |
| apps/common-app/src/new_api/calculator/index.tsx | Updates SharedValue typings in props. |
| apps/common-app/src/new_api/betterHorizontalDrawer/index.tsx | Updates SharedValue typings in helper function signature. |
| apps/common-app/src/new_api/betterHorizontalDrawer/BetterHorizonatalDrawer.tsx | Updates SharedValue typings in public props and internal props. |
| apps/common-app/src/ListWithHeader/ListWithHeader.tsx | Updates AnimatedRef typing and uses destructured props in reactions/gestures. |
| apps/common-app/src/basic/pagerAndDrawer/index.android.tsx | Migrates from deprecated viewpager package to react-native-pager-view. |
| apps/common-app/package.json | Bumps deps; adds pager-view/svg/worklets and aligns versions. |
| apps/basic-example/package.json | Bumps RN to 0.86 and adds Reanimated/Worklets dependencies. |
| apps/basic-example/metro.config.js | Removes Reanimated blacklist now that it’s installed in the app. |
| apps/basic-example/ios/Podfile.lock | Updates pods for RN 0.86 and adds Reanimated/Worklets pods. |
| apps/basic-example/ios/BasicExample.xcodeproj/project.pbxproj | Sets PODFILE_DIR build setting. |
| .github/workflows/ios-build.yml | Updates iOS CI runner/Xcode selection. |
Comments suppressed due to low confidence (1)
packages/react-native-gesture-handler/apple/RNGestureHandlerManager.mm:452
sendEventForDirectEvent:is still called in the old-arch paths (e.g. here) but the method implementation was removed below, which will break compilation for non-Fabric builds. Re-introducesendEventForDirectEvent:(old-arch only) or inline[_eventDispatcher sendEvent:event]at the call sites.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…t in LongPressGestureHandler (#4253) ## Description Fixes #4252 On Android, the `numberOfPointers` config of the LongPress gesture has been silently ignored since 2.26.0: a gesture configured with `Gesture.LongPress().numberOfPointers(3)` activates after a **single-pointer** long press, and can never activate with the configured pointer count (the second pointer trips `currentPointers > numberOfPointersRequired` and fails the handler). iOS is unaffected, since the prop maps to `UILongPressGestureRecognizer.numberOfTouchesRequired`. The cause is a one-line mix-up introduced by the factory refactor in 2.26.0. The factory's `updateConfig` assigns the config value to `handler.numberOfPointers`, which resolves to the inherited `GestureHandler.numberOfPointers` — the live pointer-count used for event payloads, overwritten with `event.pointerCount` on every motion event. The field that actually gates activation, `numberOfPointersRequired`, stays at its default of `1` and is never written from config. Before 2.26.0, the module factory called `handler.setNumberOfPointers(...)`, which set `numberOfPointersRequired` correctly. This PR routes the config value to `numberOfPointersRequired`, restoring the pre-2.26 behavior. The private-field access from the nested `Factory` matches the existing `maxDist` assignment directly above. ## Test plan - Applied this same one-liner to 2.28.0 via patch-package in an RN 0.81.5 (Expo 54, new architecture, Hermes) app that uses `Gesture.LongPress().numberOfPointers(3)` as a global gesture, and verified on an Android device: - three-pointer long press now activates the gesture (previously never fired) - single-pointer long press no longer activates it (previously fired after ~500 ms) - gestures with the default single pointer (no `numberOfPointers` set) are unaffected - Verified iOS behavior is unchanged (the fix doesn't touch the iOS path) - Repro snippet: https://gist.github.com/prashanFOMO/ad838ce8a3c77c59759b8583fe8d3393
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
j-piasecki
approved these changes
Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Cherry pick thread for release 2.32
List of PRs
getChildInDrawingOrderAtIndextestIDonFinalizereact-native/../react-nativeresolution for aliasesRNRendererimport for React Native 0.86expoto stable 56numberOfPointersconfig to the pointer requirement inLongPressGestureHandlerTest plan
Tested that example apps are built correctly