More powerful alternative to Animated library for React Native with UI thread animations and advanced gesture handling.
—
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.
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,
]}
/>
</>
);
};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>
</>
);
};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} />
</>
);
};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 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;runOnJS callsInstall with Tessl CLI
npx tessl i tessl/npm-react-native-reanimated