0Pricing
React Native Academy · درس

Worklets وتشغيل التعليمات البرمجية على خيط واجهة المستخدم

ميّزوا الدوال بصفتها worklets باستخدام التوجيه 'worklet'، وافهموا سبب تجاوز ذلك لجسر JS، واكتبوا معالجات إيماءات تحدّث القيم المشتركة مباشرةً.

Worklets وتشغيل التعليمات البرمجية على خيط واجهة المستخدم درس مجاني في React Native Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في React Native Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة React Native Academy 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

What Is a Worklet?

A worklet is a JavaScript function that Reanimated runs on the UI thread instead of the JavaScript thread. Reanimated's Babel plugin detects functions marked with the 'worklet' directive string at the top of their body and transforms them at build time into a form that can be sent to and executed on the UI thread.

Worklets are the core mechanism that allows Reanimated to process gesture data and update animations frame-by-frame at 60fps without ever involving the JavaScript thread or the bridge. They are the key architectural innovation that separates Reanimated from the classic Animated API.

function clamp(value, min, max) {
  'worklet'; // directive marks this as a worklet
  return Math.min(Math.max(value, min), max);
}

// This function can now be called inside
// useAnimatedStyle, useAnimatedGestureHandler,
// and other Reanimated hooks

The 'worklet' Directive

The 'worklet' string literal at the top of a function body is a special directive — similar to 'use strict'. The Reanimated Babel plugin scans for it and transforms the function so it can be serialized and run on the UI thread. Without this directive, calling the function from a worklet context would silently execute on the JS thread, causing potential crashes or incorrect behavior.

Functions passed to Reanimated hooks like useAnimatedStyle are automatically treated as worklets even without the directive. Regular utility functions called FROM those hooks need the directive explicitly.

// Automatically a worklet — Reanimated knows:
const animatedStyle = useAnimatedStyle(() => {
  return { opacity: opacity.value };
});

// Utility function needs explicit directive:
function mapRange(value, inMin, inMax, outMin, outMax) {
  'worklet';
  return ((value - inMin) / (inMax - inMin)) * (outMax - outMin) + outMin;
}

Why the UI Thread Matters for Gestures

Touch events on mobile are processed on the UI thread. When a user drags a finger, the device generates touch events many times per second (up to 120fps on modern devices). If gesture handling required the JavaScript thread, every touch event would cross the bridge — introducing latency that makes interactions feel laggy and unresponsive.

With worklets, the gesture handler and the animation response both run on the UI thread. The animated value updates happen in the same thread tick as the touch event, achieving true zero-latency gesture response that feels like native iOS/Android interactions.

Calling Worklets from Animated Handlers

Reanimated provides hooks like useAnimatedScrollHandler and useAnimatedGestureHandler whose callbacks run as worklets on the UI thread. Inside these callbacks you can call any function marked with 'worklet' directly, and you can read and write shared values using .value.

Writing to a shared value inside a gesture callback is how you make an animated component track the user's finger in real time — the write happens on the UI thread and the animated style reacts immediately.

import { useAnimatedScrollHandler, useSharedValue } from 'react-native-reanimated';

const scrollY = useSharedValue(0);

const scrollHandler = useAnimatedScrollHandler({
  onScroll: (event) => {
    'worklet';
    scrollY.value = event.contentOffset.y;
  },
});

runOnJS: Calling React from Worklets

Worklets run on the UI thread and cannot directly call React functions, setState, or navigation methods. When you need to trigger JavaScript-thread code from a worklet (for example, updating React state or navigating after a gesture completes), use runOnJS.

runOnJS(fn)(args) schedules the function to run on the JS thread on the next available frame. This lets gesture handlers update React state or call navigation after an interaction without breaking the worklet execution model.

import { runOnJS } from 'react-native-reanimated';

const [dismissed, setDismissed] = React.useState(false);

// Inside a gesture handler worklet:
function onSwipeComplete() {
  'worklet';
  // Cannot call setDismissed directly from UI thread!
  runOnJS(setDismissed)(true); // schedules on JS thread
}

runOnUI: Calling Worklets from JS Thread

The reverse of runOnJS is runOnUI. This lets you schedule a worklet function to execute on the UI thread from the JavaScript thread. It is useful for triggering animations from JS-thread event handlers (like button presses) while keeping the animation logic itself in a worklet.

In most cases you simply assign to sharedValue.value (which already runs on the UI thread), so runOnUI is less commonly needed. It becomes necessary when you need to batch multiple UI-thread operations atomically.

import { runOnUI } from 'react-native-reanimated';

function triggerComplexAnimation() {
  runOnUI(() => {
    'worklet';
    // These run atomically on the UI thread:
    offset.value = withSpring(200);
    scale.value = withTiming(0.8, { duration: 300 });
    opacity.value = withTiming(0.5, { duration: 300 });
  })();
}

Limitations of Worklets

Worklets are not full JavaScript — they run in a restricted environment that cannot access Node.js APIs, React hooks, component state, or the full JavaScript runtime. You cannot console.log from a worklet in production (it is a no-op). You cannot import third-party modules inside a worklet unless they explicitly support Reanimated.

Keep worklets focused on math and value computation: clamping, mapping ranges, computing physics, reading gesture data. Move everything else to the JS thread using runOnJS.

function gestureHandler(event) {
  'worklet';
  // OK in worklets:
  const clamped = Math.max(0, Math.min(event.translationX, 300));
  offset.value = clamped;

  // NOT OK in worklets:
  // console.log('position:', clamped); // no-op in prod
  // setReactState(clamped); // crashes - use runOnJS
  // navigation.navigate('Screen'); // crashes - use runOnJS
}

useAnimatedReaction for Watching Values

useAnimatedReaction lets you watch a shared value or derived expression and run a worklet (or call back to JS) when it changes. It takes two worklet functions: a prepare function that reads values, and a reaction function that receives the current and previous values.

This is useful for triggering side effects when an animation reaches a threshold — like calling navigation to dismiss a screen when an offset exceeds 50% of the screen height.

import { useAnimatedReaction, runOnJS } from 'react-native-reanimated';

useAnimatedReaction(
  () => offset.value,           // prepare: what to watch
  (currentValue, previousValue) => { // reaction: what to do
    'worklet';
    if (currentValue > 200 && previousValue <= 200) {
      runOnJS(onDismiss)(); // notify JS thread
    }
  }
);

useDerivedValue for Computed Shared Values

useDerivedValue creates a new shared value that is automatically computed from other shared values. The derivation function is a worklet that runs on the UI thread whenever any dependency changes. It is the Reanimated equivalent of useMemo, but for shared values.

Use derived values to compute complex transformations once (rather than repeating the math in each useAnimatedStyle) or to drive multiple style hooks from a single source of truth.

import { useDerivedValue } from 'react-native-reanimated';

const progress = useSharedValue(0); // 0 to 1

// Derived: convert progress to translateX
const translateX = useDerivedValue(() => {
  'worklet';
  return progress.value * 300;
});

// Derived: convert progress to opacity (inverse)
const opacity = useDerivedValue(() => {
  'worklet';
  return 1 - progress.value;
});

Worklets in Practice: Scroll Parallax

A scroll parallax header demonstrates worklets in practice. The scroll offset drives multiple derived values — a background image moves at half speed, a title fades out, and a sticky mini-header fades in. All these derivations run as worklets triggered by Animated.event scroll tracking.

The entire parallax effect runs at 60fps with zero JavaScript thread involvement because every step — scroll tracking, value derivation, and style computation — is a worklet on the UI thread.

const scrollY = useSharedValue(0);

const bgTranslateY = useDerivedValue(() => scrollY.value * 0.5);
const titleOpacity = useDerivedValue(() =>
  Math.max(0, 1 - scrollY.value / 100)
);

const bgStyle = useAnimatedStyle(() => ({
  transform: [{ translateY: bgTranslateY.value }],
}));
const titleStyle = useAnimatedStyle(() => ({
  opacity: titleOpacity.value,
}));

Debugging Worklets

Debugging worklets is harder than regular JavaScript because they run on a separate thread. Use console.log inside worklets during development (it works in debug mode via Hermes), and use useAnimatedReaction with runOnJS(console.log) for production-safe logging.

Reanimated also integrates with React DevTools Profiler to visualize which worklets are running. If animations behave unexpectedly, add a useDerivedValue to log the computed value at each frame to identify where the calculation diverges from expectations.

// Development: console.log works in Hermes debug
useAnimatedStyle(() => {
  console.log('offset:', offset.value); // OK in dev mode
  return { transform: [{ translateX: offset.value }] };
});

// Production-safe logging via runOnJS:
useAnimatedReaction(
  () => offset.value,
  (val) => runOnJS(console.log)('offset:', val)
);

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: worklets are functions marked with the 'worklet' directive that run on the UI thread bypassing the bridge, runOnJS schedules JS-thread calls from worklets for React state and navigation, and useDerivedValue and useAnimatedReaction let you derive and watch shared values in worklet context. Next up we build a draggable card using Pan gestures with React Native Gesture Handler.

الأسئلة الشائعة

هل درس «Worklets وتشغيل التعليمات البرمجية على خيط واجهة المستخدم» مجاني؟

نعم — نص درس «Worklets وتشغيل التعليمات البرمجية على خيط واجهة المستخدم» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة React Native Academy، انتقل إلى CoddyKit PRO. تتضمن دورة React Native Academy 4 دروس في المجموع.

ماذا ستتعلم في «Worklets وتشغيل التعليمات البرمجية على خيط واجهة المستخدم»؟

ميّزوا الدوال بصفتها worklets باستخدام التوجيه 'worklet'، وافهموا سبب تجاوز ذلك لجسر JS، واكتبوا معالجات إيماءات تحدّث القيم المشتركة مباشرةً. تتمرن على React Native Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ React Native Academy؟

لا تُشترط خبرة سابقة. React Native Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «Worklets وتشغيل التعليمات البرمجية على خيط واجهة المستخدم»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس React Native Academy هذا؟

نعم. كل درس في React Native Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. تثبيت Reanimated والقيم المشتركة
  2. Worklets وتشغيل التعليمات البرمجية على خيط واجهة المستخدم
  3. إيماءات السحب والتمرير باستخدام Gesture Handler
  4. التكبير والتصغير والدوران بإيماءة القرص
← العودة إلى React Native Academy