Closed nmassey closed 2 months ago
Latest commit: 17621ca772cc3f166094e1445253f77a0967a201
The changes in this PR will be included in the next version bump.
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 ↗︎
Name | Status | Preview | Comments | Updated (UTC) |
---|---|---|---|---|
react-native-reanimated-carousel | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | May 6, 2024 4:28pm |
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?
npx changeset
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!
@dohooo Would deeply appreciate if this and https://github.com/dohooo/react-native-reanimated-carousel/pull/648 are merged. Would be great to get these fixes in before we push the new version of our app to prod. If there's anything I can do to help, please let me know. (FWIW I already became a GitHub Sponsor out of my own pocket)
hi @qwertychouskie - I've been using yarn patch
to unblock me while waiting for these PRs to be merged 😕
Are you on the Discord?
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(...
here https://github.com/dohooo/react-native-reanimated-carousel/blob/main/src/hooks/usePanGestureProxy.ts#L79-L97The
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.
https://github.com/dohooo/react-native-reanimated-carousel/assets/589004/9ff5fcea-9dfa-45a4-8da1-9705192716f0
improved behavior with patch
See that all debug messages indicate the the code is running inside of worklet.
https://github.com/dohooo/react-native-reanimated-carousel/assets/589004/ba296f93-be06-4a44-beb3-2ce299801c2f
possible TODOs
onStart
/onUpdate
/onEnd
etc. code inusePanGestureProxy.ts
onChange