Fix: onPress callbacks are invoked for all nested Pressables #3295
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
Fixes #3282
The onStart and onBegin callbacks are invoked on the deepest responder on iOS and Android respectively. Inside those methods the
isTouchPropagationAllowed
ref is set to true. Base on that we can assume whichPressable
should be the responder of the touch on the JS side. Yet there is nothing that would stop invokingonPress
callbacks if theisTouchPropagationAllowed
is set to false in pressOutHandler. The fix introduces early return in thepressOutHandler
if clickedPressable
is not the deepest one.On the old architecture the measure method is called asynchronously, usually after the
onStart
. In nested pressables, if the deepest one is clicked it still callsonTouchesDown
andonTouchesUp
, which sets shouldPreventNativeEffects totrue
, omitting theonStart
, which sets it back tofalse
. Because of that, when now we tried to click on the outer Pressable it would be stopped in onStart shouldPreventNativeEvents check without setting theisTouchPropagationAllowed
totrue
and this is the exact same state that led to setting theshouldPreventNativeEffects
totrue
so it is a cycle. The simplest solution for this is to check if theonStart
is called before themeasure
inshouldPreventNativeEffects
check and early return if it's not.Test plan
Click on the red box and notice that callbacks on its parent are not invoked. Click on the text input to see that the callbacks on its Pressable parent are also not invoked.
Code