BEGAN state isn't handled if taps are very quick
See original GitHub issueDescription
Assuming even a simple JS-side reanimated-Code
block that depends on both BEGAN
and END
states (associated with down and up press events from a tap), the BEGAN
state will not be handled if the tap gesture (touch and release) is done very quickly.
In particular, we find this to be an issue with automated tests written with Detox.
For example, consider this simple usage of reanimated:
const buttonOpacity = new Value(1.0);
const gestureState = new Value(-1);
// ...
<Reanimated.Code>
{() =>
block([
cond(eq(gestureState, State.BEGAN), set(buttonOpacity, 0.25)),
cond(eq(gestureState, State.END), set(buttonOpacity, 1.0))
])
}
</Reanimated.Code>
If the tap is performed really fast, the BEGAN
will not be fired, and with that the opacity flicker will not take place.
Root cause
I’ve done some research as to what causes this and this is what I dug up.
The root of the problem - on Android, at least, is that the history of states doesn’t get recorded in ValueNode
s. Rather, ValueNode
s only keep the most recent value set to it. Combined with the fact that these updates’ handling is only triggered via the choreographer’s callback - which is only dispatched async’ly in ~16ms intervals, if the gap between events is small enough (i.e. both take place fast enough to precede the next callback exec) then you end up with the BEGAN
getting lost, and only the ACTIVE
and END
being handled.
Additional Artefacts, Reproduction
In essence, this can be reproduced by running Wix’ public RN UI-Lib project’s demo app, as explained by @ethanshar’s comment below.
Technical Info
- React native version:
0.61.5
- Reanimated version:
1.7.0
Issue Analytics
- State:
- Created 4 years ago
- Reactions:18
- Comments:11 (3 by maintainers)
Top GitHub Comments
Please take a look at the attached GIF demonstrating how the button doesn’t react to “soft” taps while “hard” taps work.
To reproduce this You can checkout this code https://github.com/wix/react-native-ui-lib/blob/demo/TouchableTapIssue/demo/src/screens/PlaygroundScreen.js
And the source code for this component can be found here https://github.com/wix/react-native-ui-lib/blob/demo/TouchableTapIssue/src/incubator/TouchableOpacity.js#L58
@kmagiera So given the situation, we’re now considering submitting a fix through a PR. I tried a few naive solutions such as maintaining a values queue inside
ValueNode
but these attempts have been futile so far (animations and state changes go crazy 😄).Do you have any suggestions as to how we should approach this, given the broader outlook on things?