home / skills / sovranbitcoin / sovran / animation-with-worklets

animation-with-worklets skill

/.agents/skills/animation-with-worklets

This skill helps you schedule cross-thread work in React Native using worklets guidelines, improving animation performance and thread safety.

npx playbooks add skill sovranbitcoin/sovran --skill animation-with-worklets

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
5.1 KB
---
name: animation-with-worklets
description: Provides React Native Worklets guidelines for scheduling functions between JS and UI threads. Applies to tasks involving scheduleOnRN, scheduleOnUI, worklets, thread scheduling, useAnimatedReaction, gesture handlers, or cross-thread function calls.
---

# Worklet Scheduling

## Overview

Guidelines for scheduling functions between JavaScript and UI threads using React Native Worklets. This skill covers when and how to use `scheduleOnRN` and `scheduleOnUI`, proper function definition patterns, and avoiding unnecessary worklet directives.

## When to Apply

Reference these guidelines when:
- Scheduling functions to run on UI thread from JS thread
- Calling JS thread functions from UI thread worklets
- Working with `useAnimatedReaction` or gesture handlers
- Batching shared value updates
- Implementing cross-thread communication in animations

## Key Guidelines

### Don't Use 'worklet' Directive Unless Explicitly Asked

**Never use the `"worklet"` directive unless explicitly requested.** In 99.9% of cases, there is no need to use it. `scheduleOnUI` handles worklet conversion automatically, so the directive is unnecessary. This also applies to gesture detector callbacks - you don't need to add the `"worklet"` directive in gesture handler callbacks.

### Use scheduleOnRN and scheduleOnUI Instead of runOnJS and runOnUI

Use `scheduleOnRN` and `scheduleOnUI` from `react-native-worklets` instead of `runOnJS` and `runOnUI` from `react-native-reanimated`.

**Don't do this:**

```tsx
import { runOnJS, runOnUI } from "react-native-reanimated";
```

**Instead, do this:**

```tsx
import { scheduleOnRN, scheduleOnUI } from "react-native-worklets";
```

### Type Definitions

```tsx
function scheduleOnRN<Args extends unknown[], ReturnValue>(
  fun:
    | ((...args: Args) => ReturnValue)
    | RemoteFunction<Args, ReturnValue>
    | WorkletFunction<Args, ReturnValue>,
  ...args: Args
): void;

function scheduleOnUI<Args extends unknown[], ReturnValue>(
  fun: (...args: Args) => ReturnValue,
  ...args: Args
): void;
```

## Usage Patterns

### Always Define Functions Outside Using useCallback

Both `scheduleOnRN` and `scheduleOnUI` follow the same usage pattern: **always define the function outside using `useCallback` and pass the function reference** (not inline arrow functions).

**When to use:**

- `scheduleOnRN`: Call JavaScript thread functions from UI thread worklets (like in `useAnimatedReaction`, gesture handlers, or `useAnimatedStyle`)
- `scheduleOnUI`: Schedule functions to run on the UI thread

**Don't do this** – inline arrow function:

```tsx
// ❌ scheduleOnRN with inline function
useAnimatedReaction(
  () => currentIndex.get(),
  (nextIndex) => {
    scheduleOnRN(() => {
      setState(newValue);
    });
  }
);

// ❌ scheduleOnUI with inline function
scheduleOnUI(() => {
  scale.set(withSpring(1.2));
});
```

**Instead**, do this – define function outside:

```tsx
// ✅ scheduleOnRN - JS thread function
const updateState = useCallback(() => {
  setState(newValue);
}, [dependencies]);

useAnimatedReaction(
  () => currentIndex.get(),
  (nextIndex) => {
    scheduleOnRN(updateState); // pass function reference
  }
);

// ✅ scheduleOnUI - UI thread function
const updateAnimations = useCallback(() => {
  scale.set(withSpring(1.2));
  opacity.set(withSpring(0.8));
}, []);

scheduleOnUI(updateAnimations); // pass function reference
```

### Passing Arguments

Arguments are passed directly (not as an array) using rest parameter syntax:

```tsx
// Single argument
const updateState = useCallback((newValue: number) => {
  setState(newValue);
}, []);

scheduleOnRN(updateState, newValue); // ✅ correct

// Multiple arguments
const handleUpdate = useCallback((index: number, value: string) => {
  setState({ index, value });
}, []);

scheduleOnRN(handleUpdate, index, value); // ✅ correct - pass directly, not as array
scheduleOnUI(handleUpdate, index, value); // ✅ same pattern for scheduleOnUI
```

## Common Use Cases

### scheduleOnRN Use Cases

- React state setters (`setState`, `setExtendedSlides`, etc.)
- API calls or side effects
- Video player controls (`pause`, `resume`, `seek`)
- Haptic feedback
- Navigation functions

**Example:**

```tsx
// scheduleOnRN example
const pause = useCallback(() => {
  videoPlayerRef.current?.pause();
}, []);

useAnimatedReaction(
  () => isDragging.get(),
  (current) => {
    if (current) {
      scheduleOnRN(pause);
    }
  }
);
```

### scheduleOnUI Use Cases

- Batch multiple shared value updates in the same frame
- UI thread worklet operations

**Example:**

```tsx
// scheduleOnUI example - batch updates
const batchUpdates = useCallback(() => {
  scale.set(withSpring(1.2));
  opacity.set(withSpring(0.8));
}, []);

scheduleOnUI(batchUpdates);
```

## Benefits

- **Automatic Worklet Conversion**: `scheduleOnUI` handles worklet conversion automatically
- **Better Performance**: Batching updates reduces UI thread overhead
- **Type Safety**: Better TypeScript support with proper type definitions
- **Cleaner Code**: No need for `"worklet"` directive in most cases
- **Consistent API**: Unified approach for cross-thread communication

Overview

This skill provides concise React Native Worklets guidelines for scheduling functions between JavaScript and UI threads. It explains when to use scheduleOnRN and scheduleOnUI, recommended function-definition patterns, and how to avoid unnecessary worklet directives. The guidance targets animation, gesture handlers, and cross-thread communication in mobile apps.

How this skill works

The skill inspects common scheduling patterns and recommends using scheduleOnRN and scheduleOnUI from react-native-worklets instead of runOnJS/runOnUI. It enforces defining callback functions outside of inline handlers (typically with useCallback) and passing references plus direct arguments. It also advises against using the "worklet" directive except when explicitly required because scheduleOnUI performs conversion automatically.

When to use it

  • When scheduling UI-thread work from the JS thread (animations, batched shared-value changes).
  • When calling JS-thread logic from UI-thread worklets (state updates, API calls, navigation).
  • Inside useAnimatedReaction, gesture handlers, or useAnimatedStyle where cross-thread calls occur.
  • When batching multiple shared-value updates to reduce UI thread overhead.
  • When implementing haptics, video controls, or other side effects triggered by gestures or animations.

Best practices

  • Always define scheduled functions outside the callback and memoize with useCallback; pass the function reference instead of an inline arrow.
  • Use scheduleOnRN for JS-thread work (state setters, API calls, navigation, haptics) and scheduleOnUI for UI-thread operations and batched shared-value updates.
  • Pass arguments directly as separate parameters (rest args), not as an array. Example: scheduleOnRN(fn, arg1, arg2).
  • Avoid the "worklet" directive in almost all cases; scheduleOnUI handles conversion automatically and gesture callbacks usually don’t need the directive.
  • Prefer the react-native-worklets API over react-native-reanimated runOnJS/runOnUI for better type safety and consistent behavior.

Example use cases

  • Update React state from a UI-thread reaction: useAnimatedReaction -> scheduleOnRN(stateSetter).
  • Batch two shared-value updates on the UI thread: define a memoized batch function and call scheduleOnUI(batchUpdates).
  • Trigger video controls or haptic feedback from a gesture handler using scheduleOnRN(controlFunction).
  • Call navigation or API side effects from an animation callback via scheduleOnRN(navigationOrApiCall).
  • Batch visual spring animations together on UI thread to reduce frame overhead with scheduleOnUI(batchAnimations).

FAQ

Do I need to add the "worklet" directive to my scheduled functions?

No. Avoid the "worklet" directive unless explicitly required. scheduleOnUI will handle conversion in almost all cases.

Should I ever use inline arrow functions with scheduleOnRN/scheduleOnUI?

No. Inline functions break memoization patterns and can cause unnecessary re-registrations. Define functions outside (useCallback) and pass the reference.