CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-native-reanimated

More powerful alternative to Animated library for React Native with UI thread animations and advanced gesture handling.

Pending
Overview
Eval results
Files

worklet-functions.mddocs/

Worklet Functions

Functions for executing code on the UI thread and managing worklet runtimes, enabling high-performance animations and computations that run independently of the JavaScript thread.

IMPORTANT: These functions are deprecated in React Native Reanimated and users should import them directly from react-native-worklets instead. They are re-exported here for compatibility but may be removed in future versions.

Capabilities

Thread Execution Control

Functions to execute code on different threads for optimal performance.

/**
 * Executes a worklet function on the UI thread
 * @deprecated Import directly from react-native-worklets instead
 * @param worklet - Function to execute on UI thread (must be a worklet)
 * @returns Function that can be called from JS thread to trigger UI execution
 */
function runOnUI<Args extends readonly unknown[], Return>(
  worklet: WorkletFunction<Args, Return>
): (...args: Args) => void;

/**
 * Executes a JavaScript function on the JS thread from a worklet
 * @deprecated Import directly from react-native-worklets instead
 * @param jsFunction - JavaScript function to execute on JS thread
 * @returns Worklet function that can be called from UI thread
 */
function runOnJS<Args extends readonly unknown[], Return>(
  jsFunction: (...args: Args) => Return
): WorkletFunction<Args, void>;

/**
 * Executes a worklet on a specific runtime
 * @deprecated Import directly from react-native-worklets instead
 * @param runtime - Target worklet runtime
 * @param worklet - Worklet function to execute
 * @returns Function to trigger execution on the specified runtime
 */
function runOnRuntime<Args extends readonly unknown[], Return>(
  runtime: WorkletRuntime,
  worklet: WorkletFunction<Args, Return>
): (...args: Args) => void;

Usage Examples:

import React from "react";
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  runOnUI,
  runOnJS,
  withTiming
} from "react-native-reanimated";
import { Button } from "react-native";

const WorkletExample = () => {
  const progress = useSharedValue(0);

  // Function to run on JS thread
  const logProgress = (value: number) => {
    console.log(`Animation progress: ${value}`);
  };

  // Worklet function (runs on UI thread)
  const animateWithLogging = (targetValue: number) => {
    'worklet';
    progress.value = withTiming(targetValue, { duration: 1000 }, (finished) => {
      'worklet';
      if (finished) {
        // Call JS function from worklet using runOnJS
        runOnJS(logProgress)(targetValue);
      }
    });
  };

  // UI thread computation worklet
  const complexCalculation = (input: number): number => {
    'worklet';
    // Heavy computation that runs on UI thread
    let result = input;
    for (let i = 0; i < 1000; i++) {
      result = Math.sin(result) * Math.cos(result) + input;
    }
    return result;
  };

  const animatedStyle = useAnimatedStyle(() => {
    // Using complex calculation in worklet context
    const computedValue = complexCalculation(progress.value);
    
    return {
      opacity: progress.value,
      transform: [
        { scale: 1 + progress.value * 0.5 },
        { rotate: `${computedValue * 360}deg` }
      ],
    };
  });

  // Run worklet on UI thread
  const handlePress = () => {
    runOnUI(animateWithLogging)(progress.value === 0 ? 1 : 0);
  };

  // Alternative: direct worklet call
  const handleDirectCall = () => {
    animateWithLogging(Math.random());
  };

  return (
    <>
      <Button title="Animate with Logging" onPress={handlePress} />
      <Button title="Random Animation" onPress={handleDirectCall} />
      
      <Animated.View
        style={[
          {
            width: 100,
            height: 100,
            backgroundColor: "lightblue",
            borderRadius: 10,
            margin: 20,
          },
          animatedStyle,
        ]}
      />
    </>
  );
};

Runtime Management

Create and manage custom worklet runtimes for specialized execution contexts.

/**
 * Creates a new worklet runtime with optional name
 * @deprecated Import directly from react-native-worklets instead
 * @param name - Optional name for the runtime (for debugging)
 * @returns New WorkletRuntime instance
 */
function createWorkletRuntime(name?: string): WorkletRuntime;

/**
 * Executes a worklet synchronously on the UI runtime
 * @deprecated Import directly from react-native-worklets instead
 * @param worklet - Worklet function to execute
 * @returns Return value from the worklet execution
 */
function executeOnUIRuntimeSync<T>(worklet: () => T): T;

interface WorkletRuntime {
  /** Runtime identifier */
  __workletRuntimeId: number;
}

Usage Examples:

import React, { useEffect, useState } from "react";
import Animated, {
  createWorkletRuntime,
  runOnRuntime,
  executeOnUIRuntimeSync,
  useSharedValue
} from "react-native-reanimated";

const RuntimeExample = () => {
  const [result, setResult] = useState<number>(0);
  const [customRuntime, setCustomRuntime] = useState<WorkletRuntime | null>(null);
  const sharedCounter = useSharedValue(0);

  useEffect(() => {
    // Create custom runtime
    const runtime = createWorkletRuntime("CustomCalculationRuntime");
    setCustomRuntime(runtime);

    return () => {
      // Runtime cleanup would happen here if needed
    };
  }, []);

  // Heavy computation worklet for custom runtime
  const heavyComputation = (iterations: number): number => {
    'worklet';
    let result = 0;
    for (let i = 0; i < iterations; i++) {
      result += Math.sqrt(i) * Math.sin(i / 100);
    }
    return result;
  };

  // Worklet for UI runtime
  const updateCounter = () => {
    'worklet';
    sharedCounter.value += 1;
    return sharedCounter.value * 2;
  };

  const runCustomCalculation = () => {
    if (customRuntime) {
      // Run heavy computation on custom runtime
      runOnRuntime(customRuntime, (iterations: number) => {
        'worklet';
        const result = heavyComputation(iterations);
        // Cannot directly update state from worklet, need runOnJS
        runOnJS(setResult)(result);
      })(10000);
    }
  };

  const runSyncCalculation = () => {
    // Execute synchronously on UI runtime
    const result = executeOnUIRuntimeSync(updateCounter);
    setResult(result);
  };

  return (
    <>
      <Button title="Run Custom Runtime Calculation" onPress={runCustomCalculation} />
      <Button title="Run Sync UI Calculation" onPress={runSyncCalculation} />
      
      <Text>Result: {result}</Text>
      <Text>Counter: {sharedCounter.value}</Text>
    </>
  );
};

Worklet Utilities

Utility functions for working with worklets and shareable values.

/**
 * Checks if a value is a worklet function
 * @deprecated Import directly from react-native-worklets instead
 * @param value - Value to check
 * @returns True if the value is a worklet function
 */
function isWorkletFunction(value: unknown): boolean;

/**
 * Creates a deep shareable clone of a value for cross-thread usage
 * @deprecated Import directly from react-native-worklets instead
 * @param value - Value to make shareable
 * @returns Shareable clone of the value
 */
function makeShareableCloneRecursive<T>(value: T): T;

Usage Examples:

import React from "react";
import Animated, {
  isWorkletFunction,
  makeShareableCloneRecursive,
  useSharedValue,
  runOnUI
} from "react-native-reanimated";

const WorkletUtilsExample = () => {
  const sharedValue = useSharedValue(0);

  // Regular function
  const regularFunction = (x: number) => x * 2;

  // Worklet function
  const workletFunction = (x: number) => {
    'worklet';
    return x * 2;
  };

  // Complex object to share
  const complexData = {
    numbers: [1, 2, 3, 4, 5],
    config: {
      duration: 1000,
      easing: "ease-in-out",
    },
    compute: (value: number) => value * Math.PI,
  };

  const checkFunctions = () => {
    console.log("Regular function is worklet:", isWorkletFunction(regularFunction));
    console.log("Worklet function is worklet:", isWorkletFunction(workletFunction));
  };

  const shareComplexData = () => {
    // Make complex data shareable across threads
    const shareableData = makeShareableCloneRecursive(complexData);
    
    runOnUI((data) => {
      'worklet';
      // Can safely use shareableData on UI thread
      const result = data.numbers.reduce((sum, num) => sum + num, 0);
      console.log("Sum calculated on UI thread:", result);
    })(shareableData);
  };

  // Example of sharing configuration objects
  const animationConfig = makeShareableCloneRecursive({
    spring: {
      damping: 15,
      stiffness: 150,
    },
    timing: {
      duration: 800,
      easing: "ease-out",
    },
  });

  const useSharedConfig = () => {
    runOnUI((config) => {
      'worklet';
      // Use shared configuration on UI thread
      sharedValue.value = withSpring(1, config.spring);
    })(animationConfig);
  };

  return (
    <>
      <Button title="Check Function Types" onPress={checkFunctions} />
      <Button title="Share Complex Data" onPress={shareComplexData} />
      <Button title="Use Shared Config" onPress={useSharedConfig} />
    </>
  );
};

Advanced Worklet Patterns

Complex worklet usage patterns and best practices.

Performance-Optimized Worklets:

import React from "react";
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  useDerivedValue,
  runOnUI,
  runOnJS
} from "react-native-reanimated";

const AdvancedWorkletExample = () => {
  const touches = useSharedValue<Array<{x: number, y: number}>>([]);
  const canvasSize = useSharedValue({ width: 300, height: 300 });

  // Heavy computation worklet
  const processGestureData = useDerivedValue(() => {
    'worklet';
    const touchArray = touches.value;
    
    if (touchArray.length < 2) return null;
    
    // Calculate center point
    const centerX = touchArray.reduce((sum, touch) => sum + touch.x, 0) / touchArray.length;
    const centerY = touchArray.reduce((sum, touch) => sum + touch.y, 0) / touchArray.length;
    
    // Calculate distances for scaling
    const distances = touchArray.map(touch => 
      Math.sqrt(Math.pow(touch.x - centerX, 2) + Math.pow(touch.y - centerY, 2))
    );
    
    const averageDistance = distances.reduce((sum, dist) => sum + dist, 0) / distances.length;
    
    return {
      center: { x: centerX, y: centerY },
      scale: Math.max(0.5, Math.min(3, averageDistance / 100)),
      rotation: Math.atan2(touchArray[1].y - touchArray[0].y, touchArray[1].x - touchArray[0].x)
    };
  });

  // Optimized animation worklet
  const animatedStyle = useAnimatedStyle(() => {
    const gestureData = processGestureData.value;
    
    if (!gestureData) {
      return { opacity: 0.5 };
    }
    
    return {
      opacity: 1,
      transform: [
        { translateX: gestureData.center.x - canvasSize.value.width / 2 },
        { translateY: gestureData.center.y - canvasSize.value.height / 2 },
        { scale: gestureData.scale },
        { rotate: `${gestureData.rotation}rad` },
      ],
    };
  });

  // Batched UI updates worklet
  const batchedUpdates = (updates: Array<() => void>) => {
    'worklet';
    // Batch multiple updates for better performance
    updates.forEach(update => update());
  };

  const handleMultipleUpdates = () => {
    runOnUI(batchedUpdates)([
      () => {
        'worklet';
        touches.value = [
          { x: Math.random() * 300, y: Math.random() * 300 },
          { x: Math.random() * 300, y: Math.random() * 300 },
        ];
      },
      () => {
        'worklet';
        canvasSize.value = { 
          width: 300 + Math.random() * 100, 
          height: 300 + Math.random() * 100 
        };
      },
    ]);
  };

  return (
    <>
      <Button title="Update Gesture Data" onPress={handleMultipleUpdates} />
      
      <Animated.View
        style={[
          {
            width: 100,
            height: 100,
            backgroundColor: "lightcoral",
            borderRadius: 10,
          },
          animatedStyle,
        ]}
      />
    </>
  );
};

Error Handling in Worklets:

const errorHandlingWorklet = (value: number) => {
  'worklet';
  try {
    // Risky operation
    const result = complexCalculation(value);
    return result;
  } catch (error) {
    // Handle errors in worklet context
    runOnJS(console.error)('Worklet error:', error);
    return 0; // Fallback value
  }
};

Type Definitions

type WorkletFunction<Args extends readonly unknown[], Return> = 
  ((...args: Args) => Return) & { __workletHash?: number };

interface WorkletRuntime {
  __workletRuntimeId: number;
}

type ShareableRef<T> = {
  value: T;
} & { __reanimatedShareableRef: true };

// Utility types for worklet context
type WorkletContext = {
  _WORKLET: boolean;
  _IS_WORKLET_RUNTIME: boolean;
};

// Shareable value constraints
type Shareable<T> = T extends Function 
  ? WorkletFunction<any[], any>
  : T extends object
  ? { [K in keyof T]: Shareable<T[K]> }
  : T;

Best Practices

Worklet Performance Tips

  1. Minimize JS-UI thread communication: Avoid frequent runOnJS calls
  2. Use derived values: Compute dependent values on the UI thread
  3. Batch operations: Group multiple updates together
  4. Cache expensive calculations: Store results in shared values when possible
  5. Profile performance: Use timing measurements to identify bottlenecks

Common Pitfalls

  1. Closures in worklets: Be careful with captured variables
  2. Async operations: Worklets are synchronous, avoid async/await
  3. External dependencies: Don't reference non-worklet functions directly
  4. Memory leaks: Clean up event listeners and runtimes properly
  5. Error handling: Always handle potential errors in worklets

Install with Tessl CLI

npx tessl i tessl/npm-react-native-reanimated

docs

animated-components.md

animation-functions.md

configuration-utilities.md

core-reactive-system.md

css-integration.md

event-handling.md

index.md

interpolation-easing.md

layout-animations.md

platform-functions.md

screen-transitions.md

testing-utilities.md

worklet-functions.md

tile.json