[General] Don't emit duplicate events for NativeViewGestureHandler#4102
Merged
j-piasecki merged 3 commits intomainfrom Apr 22, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Reduces noise from NativeViewGestureHandler by suppressing redundant “active update” events when the emitted payload hasn’t changed, lowering dispatch overhead across web, iOS, and Android.
Changes:
- Web: add a per-handler snapshot comparison to suppress duplicate ACTIVE update events for
NativeViewGestureHandler. - Web: introduce an overridable suppression hook in the base
GestureHandlerfor V3 update events. - Native (iOS/Android): suppress redundant ACTIVE update events by snapshotting the payload fields and only emitting on change.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/react-native-gesture-handler/src/web/handlers/NativeViewGestureHandler.ts | Tracks last ACTIVE handlerData and suppresses duplicate update events via deep equality. |
| packages/react-native-gesture-handler/src/web/handlers/GestureHandler.ts | Adds shouldSuppressActiveUpdate() hook and applies it to V3 ACTIVE update event dispatch. |
| packages/react-native-gesture-handler/apple/Handlers/RNNativeViewHandler.mm | Adds caching of last ACTIVE extraData to avoid emitting unchanged ACTIVE events for UIControl-driven native views. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/NativeViewGestureHandler.kt | Suppresses duplicate ACTIVE updates by comparing a lightweight snapshot before dispatching handler updates. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
m-bert
reviewed
Apr 21, 2026
m-bert
approved these changes
Apr 21, 2026
m-bert
added a commit
that referenced
this pull request
Apr 28, 2026
## Description I've noticed that when `Native` gesture is not attached to `UIControl` it sends different events (e.g. events containing `x` and `y` positions). I've changed that to mimic behavior from #4102 ## Test plan <details> <summary>Tested on the following example</summary> ```tsx import { ScrollView, StyleSheet, View } from 'react-native'; import { GestureDetector, GestureHandlerRootView, ScrollView as RNGHScrollView, Touchable, useNativeGesture, } from 'react-native-gesture-handler'; export default function App() { const g = useNativeGesture({ onBegin: () => { console.log(Date.now(), 'gesture begin'); }, onActivate: () => { console.log(Date.now(), 'gesture activate'); }, onUpdate: (e) => { console.log(Date.now(), 'gesture update', e); }, onDeactivate: () => { console.log(Date.now(), 'gesture deactivate'); }, onFinalize: () => { console.log(Date.now(), 'gesture finalize'); }, shouldCancelWhenOutside: false, }); return ( <GestureHandlerRootView style={styles.container}> <Touchable cancelOnLeave={false} style={{ width: 150, height: 45, backgroundColor: 'crimson', borderRadius: 8, }} /> <GestureDetector gesture={g}> <ScrollView style={[styles.scrollView, { backgroundColor: 'green' }]}> {BOXES.map((color, i) => ( <View key={i} style={[styles.box, { backgroundColor: color }]} /> ))} </ScrollView> </GestureDetector> <RNGHScrollView onBegin={() => { console.log(Date.now(), 'gesture begin'); }} onActivate={() => { console.log(Date.now(), 'gesture activate'); }} onUpdate={() => { console.log(Date.now(), 'gesture update'); }} onDeactivate={() => { console.log(Date.now(), 'gesture deactivate'); }} onFinalize={() => { console.log(Date.now(), 'gesture finalize'); }} style={[styles.scrollView, { backgroundColor: 'blue' }]}> {BOXES.map((color, i) => ( <View key={i} style={[styles.box, { backgroundColor: color }]} /> ))} </RNGHScrollView> </GestureHandlerRootView> ); } const BOXES = [ '#ff6b6b', '#ffd93d', '#6bcb77', '#4d96ff', '#c77dff', '#ff9f43', '#ee5a24', '#0652dd', '#1289a7', '#d980fa', ]; const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, scrollView: { width: 200, maxHeight: 250, marginVertical: 8, }, box: { width: '100%', height: 60, marginBottom: 4, }, }); ``` </details>
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
Updates
NativeViewGestureHandlernot to emit update event on every pointer move unless the payload would change. This significantly reduces the number of events dispatched by the native gesture handlers, which should have a positive impact on performance without causing any information loss.Supersedes #3348
Test plan
Add
onUpdate={console.log}to the internalTouchableimplementation and check any example usingTouchable.