-
-
Notifications
You must be signed in to change notification settings - Fork 338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: gesture onStart
, onUpdate
, and onEnd
(et al) should be worklets
#577
Conversation
…rkletified, so be explicit
…letify and handle these, too
🦋 Changeset detectedLatest commit: 17621ca The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Note: this PR may also resolve the underlying issues for:
That being said, I still recommend those PRs in addition to this PR for code clarity's sake. |
when it would be merged? |
Incredible work, thank you! But before merging, could you gen a changeset for this PR?
|
Hi, is there a reason why this PR fix was not yet merged in? It's been open and stale for quite some time... Thank you for your amazing work! |
hi @qwertychouskie - I've been using |
What: the bug
The
onStart
,onUpdate
, andonEnd
gesture handlers are not being automatically workletized. This causes these handlers to run on the JS thread instead of the UI thread, and this is causing a number of issues, including animations running more slowly and some data (viauseSharedData
) being set asynchronously, leading to some race conditions.(See more discussion below in "Discussion of the bug".)
What: fix the code
Add
"worklet"
directives for each gesture handler function.What: fix the tests
The tests (in
src/hooks/usePanGestureProxy.test.tsx
) also includeonBegin
andonFinalize
handlers. Since the tests include these, I decided to add some functions to support them insrc/hooks/usePanGestureProxy.ts
using the same method as foronStart
,onUpdate
, andonEnd
.If some handlers for a given gesture are workletized and some are not, RNGH will show a runtime error like the following:
Let's make sure that that error doesn't appear in our tests.
Ideally, we could test to ensure that the handler functions actually end up workletized. This would be a good follow-on TODO.
Discussion of the bug
This [lack of workletization] seems to have been accidentally introduced in:
In particular, the following change
https://github.com/dohooo/react-native-reanimated-carousel/pull/507/files#diff-519aac449991f2daef8d2cf263d4dcc9cb7c067210ac7e1d218cf9f31881f890L365-L368
old code (worked to correctly workletify) -
4.0.0-alpha.5
and earlierthe handlers were set up via
Gesture.Pan().onBegin(onGestureBegin)...
https://github.com/dohooo/react-native-reanimated-carousel/blame/5e3c3015346994eafb8c898a4ba1d345568f5ee2/src/components/ScrollViewGesture.tsx#L365-L368
Each handler function (e.g.
onGestureBegin
) was set up as a"worklet"
, e.g. https://github.com/dohooo/react-native-reanimated-carousel/blame/5e3c3015346994eafb8c898a4ba1d345568f5ee2/src/components/ScrollViewGesture.tsx#L264-L266new code (borked, not automatically workletified) -
4.0.0-alpha.6
and laterthe handlers are set up via
const gesture = Gesture.Pan();
then latergesture.onStart(...
herehttps://github.com/dohooo/react-native-reanimated-carousel/blob/main/src/hooks/usePanGestureProxy.ts#L79-L97
The
onStart
/onUpdate
/onGestureEnd
do not include the"worklet"
directive at the start of their functions.But why doesn't the
react-native-reanimated/plugin
babel plugin automatically workletify these handlers?Unfortunately, that plugin can only automatically workletify functions when they are defined via
Gesture.Pan().onStart
(or similar). The fact that we instead defineconst gesture = Gesture.Pan();
in one place and then later callgesture.onStart()
/gesture.onUpdate()
/gesture.onEnd()
means that the babel plugin doesn't find these and automatically workletify them.Source: https://github.com/software-mansion/react-native-reanimated/blob/main/plugin/src/gestureHandlerAutoworkletization.ts
Screengrab video recordings
These recordings were taken on a simulator and include
console.log
output indicating whether each call to a gesture handler is running in a worklet or not. The code to output these console log messages is shown here:non-worklet behavior on
4.0.0-alpha.10
(unpatched except forconsole.log
messages)See that all debug messages indicate that the code is not running inside of worklet.
Untitled.mov
improved behavior with patch
See that all debug messages indicate the the code is running inside of worklet.
Untitled3.mov
possible TODOs
onStart
/onUpdate
/onEnd
etc. code inusePanGestureProxy.ts
onChange