React Native Worklets Core
react-native-worklets-core is a foundational library providing a robust Worklet runner for React Native applications. It enables developers to define and execute JavaScript functions (known as Worklets) on a separate UI or native thread, distinct from the main JavaScript thread. This capability is crucial for achieving smooth animations and performance-intensive tasks without blocking the UI. The current stable version is 1.6.3, with an active development cadence including regular bug fixes and feature releases, alongside ongoing beta development for version 2.0.0. Unlike React Native Reanimated, which deeply integrates Worklets into its animation API, react-native-worklets-core aims for a more flexible, lower-level Worklet architecture. This design allows it to serve primarily as a peer dependency for other complex C++ integrated modules like react-native-vision-camera, react-native-wishlist, and react-native-skia, providing a portable and extensible Worklet runtime that facilitates easier integration with diverse native libraries and custom UI components.
Common errors
-
Property '_WORKLET' doesn't exist
cause The Babel plugin `react-native-worklets-core/plugin` is missing or incorrectly configured, failing to transform the worklet function.fixVerify `['react-native-worklets-core/plugin']` is present in your `babel.config.js` under the `plugins` array. Ensure you have restarted Metro with `yarn start --reset-cache` or `npm start -- --reset-cache`. -
Invariant Violation: Calling synchronous methods on native modules is not supported in JSC
cause Attempting to run a Worklet-enabled function in an environment where the Worklet runtime is not properly initialized or available, often indicating an issue with the native module setup.fixConfirm that the `react-native-worklets-core` native modules are correctly linked and built for your platform. For iOS, ensure `pod install` was run. For Android, check `build.gradle` and `CMakeLists.txt` configurations. Clear Metro cache and rebuild native modules. -
Android build issues: dependent libraries can't link RNWC
cause Older versions of `react-native-worklets-core` had class naming conflicts or build script issues on Android, preventing dependent libraries from linking correctly.fixUpgrade to `react-native-worklets-core` version 1.6.1 or newer, which includes fixes for Android build issues and class naming conflicts (renamed `WorkletsCore`). Clean your Android build cache (`./gradlew clean`) and rebuild. -
Error: Metro has encountered an error: Requiring module '...' which is not enabled.
cause Often seen after installing new native modules or Babel plugins, indicating Metro's cache is stale and hasn't picked up the new configuration.fixRestart Metro Bundler with a clean cache: `yarn start --reset-cache` or `npm start -- --reset-cache`.
Warnings
- breaking Version 1.4.0 and higher of react-native-worklets-core requires React Native 0.74 or higher. This is due to added support for Nitro HybridObjects, which leverages newer React Native architecture features.
- breaking For React Native versions 0.82 and above, the internal Hermes VM library name has been changed from `libhermes` to `hermesvm`. This requires an update to `react-native-worklets-core` to correctly link against Hermes.
- gotcha The Babel plugin `react-native-worklets-core/plugin` is mandatory and must be correctly configured in your `babel.config.js` file. Forgetting this step will prevent functions marked with `'worklet'` from being transformed, leading to runtime errors where worklets are not recognized.
- gotcha When integrating `react-native-worklets-core` in existing libraries or custom modules, ensure proper native linking for both iOS (Podfile) and Android (build.gradle and CMakeLists.txt) to avoid build failures or runtime crashes.
- deprecated The `Worklets` library is not tested on the Legacy Architecture (Paper). It is highly recommended to migrate to the New Architecture (Fabric) for optimal compatibility and performance.
Install
-
npm install react-native-worklets-core -
yarn add react-native-worklets-core -
pnpm add react-native-worklets-core
Imports
- Worklet type
import type { Worklet } from 'react-native-worklets-core' - Babel plugin
import 'react-native-worklets-core/plugin'
plugins: [["react-native-worklets-core/plugin"]]
- Worklets global object
import { Worklets } from 'react-native-worklets-core'Worklets.defaultContext.runAsync(myWorklet)
- useRunOnJS hook
import { useRunOnJS } from 'react-native-worklets-core'
Quickstart
import React, { useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { Worklets, useRunOnJS } from 'react-native-worklets-core';
// Important: Add the babel plugin to your babel.config.js:
// module.exports = {
// plugins: [
// ["react-native-worklets-core/plugin"],
// // ... other plugins
// ],
// // ...
// };
const logFromJS = (message) => {
console.log(`[JS Thread] ${message}`);
};
export default function App() {
// Memoize the JS callback to be safely called from a worklet
const logFromJSWorklet = useRunOnJS(logFromJS, []);
useEffect(() => {
// Define a worklet function
const heavyWorklet = () => {
'worklet'; // The worklet pragma is crucial
let sum = 0;
for (let i = 0; i < 100000000; i++) {
sum += Math.sqrt(i);
}
const message = `Calculation complete: ${sum.toFixed(2)}`;
logFromJSWorklet(message); // Call back to JS thread from worklet
};
// Run the worklet on a default background context
Worklets.defaultContext.runAsync(heavyWorklet);
console.log('[Main App] Initiating heavy worklet...');
}, [logFromJSWorklet]);
return (
<View style={styles.container}>
<Text style={styles.text}>Check your Metro logs for Worklet output!</Text>
<Text style={styles.subText}>Heavy calculation running on a background thread.</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f0f0f0',
},
text: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 10,
},
subText: {
fontSize: 14,
color: '#666',
},
});