[Web] Don't call cancel on unregistered handlers - #4134
Merged
Conversation
Co-authored-by: Copilot <copilot@github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a web-specific edge case where a gesture handler could be cancelled twice (once while tracked by the orchestrator and then again via a later pointercancel), causing the second cancel to occur after the handler had already been untracked/reset and leaving it stuck in CANCELLED until re-registered.
Changes:
- Add an orchestrator helper to check whether a handler is currently recorded.
- Guard
onPointerCancelsocancel()is only invoked when the handler is still registered in the orchestrator.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/react-native-gesture-handler/src/web/tools/GestureHandlerOrchestrator.ts | Adds isHandlerRecorded() to allow callers to verify orchestrator registration before attempting cancellation. |
| packages/react-native-gesture-handler/src/web/handlers/GestureHandler.ts | Prevents pointercancel from calling cancel() on handlers that are no longer tracked by the orchestrator. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
m-bert
approved these changes
Apr 30, 2026
m-bert
approved these changes
Apr 30, 2026
m-bert
left a comment
Collaborator
There was a problem hiding this comment.
Maybe we could also use it in recordHandlerIfNotPresent?
Base automatically changed from
@jpiasecki/remove-explicit-reset-on-cancel
to
main
April 30, 2026 09:43
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
On web, it was possible for a handler to get canceled twice: once by some internal condition, and once by
pointercancelevent. The first time was handled correctly, since the orchestrator tracked the gesture, and it was reset correctly after being canceled. The second time, the gesture was untracked after being reset and it was canceled "in the void" and it was kept in the canceled state until it was registered again, which allowed it to be cleaned properly.It's easy to reproduce with a
Touchableinside aScrollViewand starting to scroll near the very edge of the touchable. The first cancel happens when the pointer moves out of the touchable before the scroll starts, and the second one is caused by the scroll starting.This PR changes the behavior so that handlers need to be registered in the orchestrator before being canceled.
Test plan
Screen.Recording.2026-04-29.at.14.55.16.mov
Screen.Recording.2026-04-29.at.14.54.51.mov