From 270c2c098851327e6b7d744719321f8ce3a9b754 Mon Sep 17 00:00:00 2001 From: kacperkapusciak Date: Wed, 20 Nov 2024 17:06:10 +0100 Subject: [PATCH 1/4] docs: worklets on the web are just JS functions --- packages/docs-reanimated/docs/guides/worklets.mdx | 2 ++ packages/docs-reanimated/docs/threading/runOnUI.mdx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/docs-reanimated/docs/guides/worklets.mdx b/packages/docs-reanimated/docs/guides/worklets.mdx index a1a6ba2393d9..df243e4c818f 100644 --- a/packages/docs-reanimated/docs/guides/worklets.mdx +++ b/packages/docs-reanimated/docs/guides/worklets.mdx @@ -158,3 +158,5 @@ function App() { Worklets can run in other runtimes than the one provided by Reanimated. For example [VisionCamera](https://github.com/mrousavy/react-native-vision-camera) and [LiveMarkdown](https://github.com/Expensify/react-native-live-markdown) create their own worklet runtimes. You can create your own worklet runtimes with [`createWorkletRuntime`](/docs/threading/createWorkletRuntime) function. + +There's no UI thread available on the Web platform. Because of that, when Reanimated runs in the browser, worklets are resolved to plain JavaScript functions and the `'worklet';` directive has no effect. diff --git a/packages/docs-reanimated/docs/threading/runOnUI.mdx b/packages/docs-reanimated/docs/threading/runOnUI.mdx index 63e73debc392..50482039256f 100644 --- a/packages/docs-reanimated/docs/threading/runOnUI.mdx +++ b/packages/docs-reanimated/docs/threading/runOnUI.mdx @@ -71,6 +71,8 @@ import RunOnUISrc from '!!raw-loader!@site/src/examples/RunOnUI'; - Make sure not to execute `runOnUI` on the UI thread as this will result in an error. +- On the Web, `runOnUI` immediately calls the function given as the argument. In browsers there's no UI thread available. + ## Platform compatibility From cf8d59b1919c9c826dfa1849d31b1e56d2a274d4 Mon Sep 17 00:00:00 2001 From: kacperkapusciak Date: Thu, 21 Nov 2024 10:32:26 +0100 Subject: [PATCH 2/4] akchually worklet directive is useful on the web --- .../docs-reanimated/docs/guides/worklets.mdx | 72 ++++++++++++------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/packages/docs-reanimated/docs/guides/worklets.mdx b/packages/docs-reanimated/docs/guides/worklets.mdx index df243e4c818f..e91645af9f78 100644 --- a/packages/docs-reanimated/docs/guides/worklets.mdx +++ b/packages/docs-reanimated/docs/guides/worklets.mdx @@ -8,6 +8,8 @@ sidebar_position: 1 Worklets are short-running JavaScript functions that can run on the [UI thread](/docs/fundamentals/glossary#ui-thread). Reanimated uses worklets to calculate view styles and react to events on the UI thread. +## Defining worklets + You can create your own worklets using the `'worklet';` directive at the top of a function. ```javascript @@ -17,6 +19,8 @@ function myWorklet() { } ``` +## Workletization + The [Reanimated Babel Plugin](https://github.com/software-mansion/react-native-reanimated/blob/main/packages/react-native-reanimated/plugin/README-dev.md#basics) looks for functions marked with the `'worklet'` directive and converts them into serializable objects. We call this process [workletization](/docs/fundamentals/glossary#to-workletize). These objects can then be copied and run over on the UI thread. Most of the time when working with Reanimated and [Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/) the code is automatically workletized and run on the UI thread by default. @@ -32,7 +36,7 @@ function App() { } ``` -Functions marked with `'worklet';` aren't [hoisted](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting). Besides affecting hoisting, the `'worklet';` directive has no effect on the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread). +## Running worklets on the UI thread You can use [`runOnUI`](/docs/threading/runOnUI) to manually schedule worklet execution on the UI thread: @@ -60,6 +64,41 @@ function onPress() { } ``` +## Running functions from worklets + +You can run functions on the JS thread from the UI thread with [`runOnJS`](/docs/threading/runOnJS). Most frequently used to call functions that aren't marked with a `'worklet';` directive (i.e. most third-party libraries) or to update the React state. + +```javascript +import { router } from 'expo-router'; +import { Gesture } from 'react-native-gesture-handler'; + +function App() { + const tap = Gesture.Tap().onEnd(() => { + // i'm a worklet too! + // highlight-next-line + runOnJS(router.back)(); + }); +} +``` + +Functions passed to `runOnJS` must be defined in the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread) scope, i.e. in the component body or the global scope. This code won't work because `myFunction` is defined in the `withTiming` callback, which is only executed in the [UI thread](/docs/fundamentals/glossary#ui-thread): + +```javascript +function App() { + const tap = Gesture.Tap().onEnd(() => { + // myFunction is defined on the UI thread 🚨 + const myFunction = () => {}; + runOnJS(myFunction)(); // 💥 + }); +} +``` + +## Hoisting + +Functions marked with `'worklet';` aren't [hoisted](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting). Besides affecting hoisting, the `'worklet';` directive has no effect on the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread). + +## Capturing closure + Worklets are [closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures). They can access variables declared outside of their own scope. Only variables referenced in the worklet body will be captured inside the worklet scope. ```javascript @@ -94,6 +133,8 @@ function myWorklet() { } ``` +## Passing data to worklets + Worklets can return data within the same thread. ```javascript @@ -128,35 +169,14 @@ function App() { } ``` -You can run functions on the JS thread from the UI thread with [`runOnJS`](/docs/threading/runOnJS). Most frequently used to call functions that aren't marked with a `'worklet';` directive (i.e. most third-party libraries) or to update the React state. +## Using worklets on the Web -```javascript -import { router } from 'expo-router'; -import { Gesture } from 'react-native-gesture-handler'; - -function App() { - const tap = Gesture.Tap().onEnd(() => { - // i'm a worklet too! - // highlight-next-line - runOnJS(router.back)(); - }); -} -``` +There's no separate UI thread available on the Web. Because of that, when Reanimated runs in the browser, worklets are resolved to plain JavaScript functions. -Functions passed to `runOnJS` must be defined in the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread) scope, i.e. in the component body or the global scope. This code won't work because `myFunction` is defined in the `withTiming` callback, which is only executed in the [UI thread](/docs/fundamentals/glossary#ui-thread): +However, the `'worklet';` directive is still necessary on the Web, because Reanimated relies on the Babel plugin to capture dependencies inside worklet functions. -```javascript -function App() { - const tap = Gesture.Tap().onEnd(() => { - // myFunction is defined on the UI thread 🚨 - const myFunction = () => {}; - runOnJS(myFunction)(); // 💥 - }); -} -``` +## Other worklet runtimes Worklets can run in other runtimes than the one provided by Reanimated. For example [VisionCamera](https://github.com/mrousavy/react-native-vision-camera) and [LiveMarkdown](https://github.com/Expensify/react-native-live-markdown) create their own worklet runtimes. You can create your own worklet runtimes with [`createWorkletRuntime`](/docs/threading/createWorkletRuntime) function. - -There's no UI thread available on the Web platform. Because of that, when Reanimated runs in the browser, worklets are resolved to plain JavaScript functions and the `'worklet';` directive has no effect. From 3e8f97740c25d66afc1e615af832f1ddab59df2d Mon Sep 17 00:00:00 2001 From: kacperkapusciak Date: Thu, 21 Nov 2024 10:43:10 +0100 Subject: [PATCH 3/4] akcually runOnUI on the web behaves like requestAnimationFrame Co-authored-by: Tomek Zawadzki --- packages/docs-reanimated/docs/threading/runOnUI.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs-reanimated/docs/threading/runOnUI.mdx b/packages/docs-reanimated/docs/threading/runOnUI.mdx index 50482039256f..b7bc3f252605 100644 --- a/packages/docs-reanimated/docs/threading/runOnUI.mdx +++ b/packages/docs-reanimated/docs/threading/runOnUI.mdx @@ -71,7 +71,7 @@ import RunOnUISrc from '!!raw-loader!@site/src/examples/RunOnUI'; - Make sure not to execute `runOnUI` on the UI thread as this will result in an error. -- On the Web, `runOnUI` immediately calls the function given as the argument. In browsers there's no UI thread available. +- In browsers there's no separate UI thread available. Because of that, on the Web, `runOnUI` behaves just like `requestAnimationFrame`. It creates a function that, when called, will be scheduled to run with given arguments on next animation frame. ## Platform compatibility From be22b0b532dcab5f1550fc0018dec7dd9dad9e5e Mon Sep 17 00:00:00 2001 From: kacperkapusciak Date: Thu, 21 Nov 2024 11:20:35 +0100 Subject: [PATCH 4/4] akchually its similar but not exactly --- packages/docs-reanimated/docs/threading/runOnUI.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs-reanimated/docs/threading/runOnUI.mdx b/packages/docs-reanimated/docs/threading/runOnUI.mdx index b7bc3f252605..96a4452d18bf 100644 --- a/packages/docs-reanimated/docs/threading/runOnUI.mdx +++ b/packages/docs-reanimated/docs/threading/runOnUI.mdx @@ -71,7 +71,7 @@ import RunOnUISrc from '!!raw-loader!@site/src/examples/RunOnUI'; - Make sure not to execute `runOnUI` on the UI thread as this will result in an error. -- In browsers there's no separate UI thread available. Because of that, on the Web, `runOnUI` behaves just like `requestAnimationFrame`. It creates a function that, when called, will be scheduled to run with given arguments on next animation frame. +- In browsers there's no separate UI thread available. Because of that, on the Web, `runOnUI` behaves similarly to `requestAnimationFrame`. It creates a function that, when called, will be scheduled to run with given arguments on next animation frame. ## Platform compatibility