Skip to content

Commit 7df8c5a

Browse files
kacperkapusciaktomekzaw
authored andcommitted
docs: worklets on the Web are just JavaScript functions (#6737)
This PR explains the worklet behaviour on the Web and separates the [Worklets guide](https://docs.swmansion.com/react-native-reanimated/docs/guides/worklets) into easier to reference and scan sections. --------- Co-authored-by: Tomek Zawadzki <[email protected]>
1 parent 27726ec commit 7df8c5a

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

packages/docs-reanimated/docs/guides/worklets.mdx

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ sidebar_position: 1
88

99
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.
1010

11+
## Defining worklets
12+
1113
You can create your own worklets using the `'worklet';` directive at the top of a function.
1214

1315
```javascript
@@ -17,6 +19,8 @@ function myWorklet() {
1719
}
1820
```
1921

22+
## Workletization
23+
2024
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.
2125

2226
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() {
3236
}
3337
```
3438

35-
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).
39+
## Running worklets on the UI thread
3640

3741
You can use [`runOnUI`](/docs/threading/runOnUI) to manually schedule worklet execution on the UI thread:
3842

@@ -60,6 +64,41 @@ function onPress() {
6064
}
6165
```
6266

67+
## Running functions from worklets
68+
69+
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.
70+
71+
```javascript
72+
import { router } from 'expo-router';
73+
import { Gesture } from 'react-native-gesture-handler';
74+
75+
function App() {
76+
const tap = Gesture.Tap().onEnd(() => {
77+
// i'm a worklet too!
78+
// highlight-next-line
79+
runOnJS(router.back)();
80+
});
81+
}
82+
```
83+
84+
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):
85+
86+
```javascript
87+
function App() {
88+
const tap = Gesture.Tap().onEnd(() => {
89+
// myFunction is defined on the UI thread 🚨
90+
const myFunction = () => {};
91+
runOnJS(myFunction)(); // 💥
92+
});
93+
}
94+
```
95+
96+
## Hoisting
97+
98+
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).
99+
100+
## Capturing closure
101+
63102
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.
64103

65104
```javascript
@@ -94,6 +133,8 @@ function myWorklet() {
94133
}
95134
```
96135

136+
## Passing data to worklets
137+
97138
Worklets can return data within the same thread.
98139

99140
```javascript
@@ -128,32 +169,13 @@ function App() {
128169
}
129170
```
130171

131-
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.
172+
## Using worklets on the Web
132173

133-
```javascript
134-
import { router } from 'expo-router';
135-
import { Gesture } from 'react-native-gesture-handler';
174+
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.
136175

137-
function App() {
138-
const tap = Gesture.Tap().onEnd(() => {
139-
// i'm a worklet too!
140-
// highlight-next-line
141-
runOnJS(router.back)();
142-
});
143-
}
144-
```
176+
However, the `'worklet';` directive is still necessary on the Web, because Reanimated relies on the Babel plugin to capture dependencies inside worklet functions.
145177

146-
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):
147-
148-
```javascript
149-
function App() {
150-
const tap = Gesture.Tap().onEnd(() => {
151-
// myFunction is defined on the UI thread 🚨
152-
const myFunction = () => {};
153-
runOnJS(myFunction)(); // 💥
154-
});
155-
}
156-
```
178+
## Other worklet runtimes
157179

158180
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.
159181

packages/docs-reanimated/docs/threading/runOnUI.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ import RunOnUISrc from '!!raw-loader!@site/src/examples/RunOnUI';
7171

7272
- Make sure not to execute `runOnUI` on the UI thread as this will result in an error.
7373

74+
- 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.
75+
7476
## Platform compatibility
7577

7678
<PlatformCompatibility android ios web />

0 commit comments

Comments
 (0)