Skip to content
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

docs: Add Worklets page #6257

Merged
merged 13 commits into from
Jul 15, 2024
Merged
142 changes: 142 additions & 0 deletions packages/docs-reanimated/docs/guides/worklets.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
---
id: worklets
sidebar_label: Worklets
sidebar_position: 1
---

# Worklets

Worklets are short-running JavaScript functions that can be run on the [UI thread](/docs/fundamentals/glossary#ui-thread). Reanimated uses worklets to update view properties and react to events on the UI thread.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

You can create your own worklets using the `"worklet";` directive at the top of a function.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

```javascript
function myWorklet() {
'worklet';
console.log('Running on the UI thread');
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved
}
```

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 coverts 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.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

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.

```javascript
import { useAnimatedStyle } from 'react-native-reanimated';

function App() {
const style = useAnimatedStyle(() => {
// Running on the UI thread
return { opacity: 0.5 };
});
}
```

The `"worklet";` directive has no effect on the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread). Worklets on the JavaScript thread are just functions.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

You can use [`runOnUI`](/docs/threading/runOnUI) to manually run worklets on the UI thread:
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

```javascript
function myWorklet() {
'worklet';
console.log('Hello from the UI thread');
}

function onPress() {
runOnUI(myWorklet)();
}
```

You can pass data as arguments to worklets.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

```javascript
function myWorklet(greeting) {
'worklet';
console.log(`${greeting} from the UI thread`);
}

function onPress() {
runOnUI(myWorklet)('Howdy');
}
```

Worklets are [closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures). They can access variables declared outside of it's own scope. Only variables referenced in the worklet body will be captured inside the worklet scope.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

```javascript
const width = 135.5;

function otherWorklet() {
'worklet';
console.log('Captured width is', width);
}
```

Capturing big JavaScript objects inside of a worklet can lead to performance issues.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

```javascript
const theme = {...}; // theme is a big object

function myWorklet() {
'worklet';
console.log(theme.color); // 🚨 referenced `color` but captured the whole `theme` object
}
```

You can get around this problem by first assigning the prop you want to use to a separate variable .
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

```javascript
const theme = {...};
const color = theme.color;

function myWorklet() {
'worklet';
console.log(color); // ✅ captured only `color`
}
```

Worklets can return data within the same thread.

```javascript
function returningWorklet() {
'worklet';
return "I'm back"; // on the UI thread
}

function someWorklet() {
'worklet';
let what = returningWorklet(); // still on the UI thread
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved
console.log('On the UI thread, other worklet says', what);
}
```

To pass data between UI and JS thread we use [shared values](/docs/fundamentals/glossary#shared-value).

```javascript
import { useSharedValue } from 'react-native-reanimated';

function App() {
const width = useSharedValue(100);

function myWorklet() {
'worklet';
width.value += 50;
}

width.value; // available on both JS and UI thread
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved
}
```

You can run functions on the JS thread from UI thread with [`runOnJS`](/docs/threading/runOnJS). Most frequently used to call function that aren't marked with a `"worklet";` directive (i.e. most 3rd party libraries) or to update the React state.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

```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)();
});
}
```
32 changes: 17 additions & 15 deletions packages/react-native-reanimated/plugin/README-dev.md
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,28 @@ If you want to build the plugin but without using explicit `yarn`, do `yarn gene

## Table of contents:

1. [Basics](#basics)
1. [Why do we need this plugin?](#why-do-we-need-this-plugin)
1. [What is a worklet?](#what-is-a-worklet)
1. [How does a worklet work?](#how-does-a-worklet-work)
1. [Why transform worklets?](#why-transform-worklets)
1. [Automatic workletization](#automatic-workletization)
1. [Something doesn't work!](#something-doesnt-work-in-reanimated-plugin)
1. [Plugin's applications](#plugins-applications)
1. [What can be a worklet?](#what-can-be-a-worklet)
1. [Inline styles support](#inline-styles-support)
1. [How to debug?](#how-to-debug-reanimated-babel-plugin)
1. [Implementation](#implementation)
1. [Logic flowchart](#reanimated-babel-plugin-flowchart)
1. [Plugin's dependencies](#dependencies-of-reanimated-babel-plugin)
- [Reanimated Babel plugin](#reanimated-babel-plugin)
- [Table of contents:](#table-of-contents)
- [Basics](#basics)
- [Why do we need this plugin?](#why-do-we-need-this-plugin)
- [What is a worklet?](#what-is-a-worklet)
- [How does a worklet work?](#how-does-a-worklet-work)
- [Why transform worklets?](#why-transform-worklets)
- [Automatic workletization](#automatic-workletization)
- [Something doesn't work in Reanimated Plugin!](#something-doesnt-work-in-reanimated-plugin)
- [Plugin's applications](#plugins-applications)
- [What can be a worklet?](#what-can-be-a-worklet)
- [Inline styles support](#inline-styles-support)
- [How to debug Reanimated Babel plugin?](#how-to-debug-reanimated-babel-plugin)
- [Implementation](#implementation)
- [Reanimated Babel plugin flowchart](#reanimated-babel-plugin-flowchart)
- [Dependencies of Reanimated Babel plugin](#dependencies-of-reanimated-babel-plugin)

## Basics

### Why do we need this plugin?

Reanimated is all about executing the code directly on the UI thread whenever possible to avoid expensive and troublesome communication between those two threads. Since UI and JS (React-Native) contexts are separate, we somehow need to pass the functions (and their arguments) from the JS thread to the UI thread. That's why we need **worklets**. If you haven't yet, we strongly recommend reading [the official documentation on worklets](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/glossary/#worklet) first.
Reanimated is all about executing the code directly on the UI thread whenever possible to avoid expensive and troublesome communication between those two threads. Since UI and JS (React-Native) contexts are separate, we somehow need to pass the functions (and their arguments) from the JS thread to the UI thread. That's why we need **worklets**. If you haven't yet, we strongly recommend reading [the official documentation on worklets](https://docs.swmansion.com/react-native-reanimated/docs/guides/worklets) first.
kacperkapusciak marked this conversation as resolved.
Show resolved Hide resolved

### What is a worklet?

Expand Down
Loading