Worklets och kodkörning på UI-tråden
Markera funktioner som worklets med direktivet 'worklet', förstå varför detta kringgår JS-bryggan och skriv gesthanterare som uppdaterar delade värden direkt.
Worklets och kodkörning på UI-tråden är en gratis lektion i React Native Academy på CoddyKit. Detta är lektion 2 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för React Native Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i React Native Academy innehåller totalt 4 lektioner.
Vad är en worklet?
En worklet är en JavaScript-funktion som Reanimated kör på UI-tråden i stället för JavaScript-tråden. Reanimateds Babel-plugin identifierar funktioner som är markerade med direktivsträngen 'worklet' längst upp i funktionskroppen och omvandlar dem vid byggtillfället till ett format som kan skickas till och köras på UI-tråden.
Worklets är den centrala mekanism som gör att Reanimated kan behandla gestdata och uppdatera animeringar bildruta för bildruta i 60 fps utan att någonsin involvera JavaScript-tråden eller bryggan. De är den viktigaste arkitektoniska innovationen som skiljer Reanimated från det klassiska 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 hooksDirektivet 'worklet'
Strängliteralen 'worklet' längst upp i en funktionskropp är ett särskilt direktiv — ungefär som 'use strict'. Reanimateds Babel-plugin söker efter det och omvandlar funktionen så att den kan serialiseras och köras på UI-tråden. Utan detta direktiv skulle ett anrop av funktionen från en worklet-kontext i tysthet köras på JS-tråden, vilket kan orsaka krascher eller felaktigt beteende.
Funktioner som skickas till Reanimated-hooks som useAnimatedStyle behandlas automatiskt som worklets även utan direktivet. Vanliga hjälpfunktioner som anropas FRÅN dessa hooks behöver uttryckligen ha direktivet.
// 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;
}Varför UI-tråden är viktig för gester
Tryckhändelser på mobila enheter behandlas på UI-tråden. När användaren drar med ett finger genererar enheten tryckhändelser många gånger per sekund (upp till 120 fps på moderna enheter). Om gestbehandling krävde JavaScript-tråden skulle varje tryckhändelse behöva passera bryggan, vilket skapar fördröjning som får interaktioner att kännas tröga och oresponsiva.
Med worklets körs både gestbehandlingen och animeringssvar på UI-tråden. Uppdateringarna av animerade värden sker i samma trådcykel som tryckhändelsen, vilket ger en verklig gestrespons utan fördröjning och känns som inbyggda interaktioner i iOS och Android.
Anropa worklets från animerade hanterare
Reanimated tillhandahåller hooks som useAnimatedScrollHandler och useAnimatedGestureHandler, vars callback-funktioner körs som worklets på UI-tråden. I dessa callbacks kan du anropa alla funktioner som är markerade med 'worklet' direkt, och du kan läsa och skriva delade värden med hjälp av .value.
Att skriva till ett delat värde i en gestcallback är sättet du får en animerad komponent att följa användarens finger i realtid — skrivningen sker på UI-tråden och den animerade stilen reagerar omedelbart.
import { useAnimatedScrollHandler, useSharedValue } from 'react-native-reanimated';
const scrollY = useSharedValue(0);
const scrollHandler = useAnimatedScrollHandler({
onScroll: (event) => {
'worklet';
scrollY.value = event.contentOffset.y;
},
});runOnJS: anropa React från worklets
Worklets körs på UI-tråden och kan inte direkt anropa React-funktioner, setState eller navigeringsmetoder. När du behöver utlösa kod på JavaScript-tråden från en worklet (till exempel uppdatera React-tillstånd eller navigera efter att en gest har slutförts) använder du runOnJS.
runOnJS(fn)(args) schemalägger funktionen så att den körs på JS-tråden under nästa tillgängliga bildruta. På så sätt kan gest-hanterare uppdatera React-tillstånd eller anropa navigation efter en interaktion utan att bryta workletens körningsmodell.
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: anropa worklets från JS-tråden
Motsvarigheten till runOnJS är runOnUI. Den låter dig schemalägga en worklet-funktion för körning på UI-tråden från JavaScript-tråden. Det är användbart när du vill utlösa animeringar från händelsehanterare på JS-tråden (som knapptryckningar) och samtidigt behålla själva animeringslogiken i en worklet.
I de flesta fall tilldelar du helt enkelt ett värde till sharedValue.value (vilket redan körs på UI-tråden), så runOnUI behövs mer sällan. Det blir nödvändigt när du behöver samla flera operationer på UI-tråden i en atomär operation.
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 });
})();
}Begränsningar hos worklets
Worklets är inte fullständig JavaScript — de körs i en begränsad miljö som inte har åtkomst till Node.js-API:er, React-hooks, komponenttillstånd eller hela JavaScript-körmiljön. Du kan inte använda console.log från en worklet i produktion (det gör ingenting). Du kan inte importera tredjepartsmoduler i en worklet om de inte uttryckligen har stöd för Reanimated.
Håll worklets fokuserade på matematik och värdeberäkningar: begränsning av värden, mappning av intervall, beräkning av fysik och läsning av gestdata. Flytta allt annat till JS-tråden med hjälp av 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 för att bevaka värden
useAnimatedReaction låter dig bevaka ett delat värde eller ett härlett uttryck och köra en worklet (eller anropa JavaScript) när det ändras. Den tar två worklet-funktioner: en prepare-funktion som läser värden och en reaction-funktion som tar emot de aktuella och föregående värdena.
Detta är användbart när du vill utlösa sidoeffekter när en animering når ett tröskelvärde — till exempel anropa navigation för att stänga en vy när en offset överstiger 50 % av vyhöjden.
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 för beräknade delade värden
useDerivedValue skapar ett nytt delat värde som automatiskt beräknas från andra delade värden. Härledningsfunktionen är en worklet som körs på UI-tråden när någon beroende ändras. Det är Reanimateds motsvarighet till useMemo, men för delade värden.
Använd härledda värden för att beräkna komplexa omvandlingar en gång (i stället för att upprepa matematiken i varje useAnimatedStyle) eller för att styra flera stil-hooks från en enda källa till sanningen.
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 i praktiken: parallax vid scrollning
En parallaxrubrik vid scrollning visar worklets i praktiken. Scroll-offseten styr flera härledda värden — en bakgrundsbild rör sig med halva hastigheten, en titel tonas ut och en klistrad minirubrik tonas in. Alla dessa härledningar körs som worklets som utlöses av scrollspårning med Animated.event.
Hela parallaxeffekten körs i 60 fps utan någon medverkan från JavaScript-tråden, eftersom varje steg — scrollspårning, värdehärledning och stilberäkning — är en worklet på UI-tråden.
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,
}));Felsökning av worklets
Det är svårare att felsöka worklets än vanlig JavaScript eftersom de körs på en separat tråd. Använd console.log i worklets under utvecklingen (det fungerar i felsökningsläge via Hermes), och använd useAnimatedReaction med runOnJS(console.log) för loggning som är säker i produktion.
Reanimated integreras också med React DevTools Profiler för att visualisera vilka worklets som körs. Om animeringar beter sig oväntat kan du lägga till en useDerivedValue för att logga det beräknade värdet i varje bildruta och identifiera var beräkningen avviker från förväntningarna.
// 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)
);Snabbtest
Testa din förståelse av koncepten inom React Native Mobile Development från den här lektionen.
Sammanfattning av lektionen
I den här lektionen har du lärt dig att worklets är funktioner markerade med direktivet 'worklet' som körs på UI-tråden utan att passera bryggan, att runOnJS schemalägger anrop på JS-tråden från worklets för React-tillstånd och navigation och att useDerivedValue och useAnimatedReaction låter dig härleda och bevaka delade värden i en worklet-kontext. Härnäst bygger vi ett dragbart kort med Pan-gester och React Native Gesture Handler.
Lär dig JavaScript med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 30
- Lektioner
- 120
Vanliga frågor
Är lektionen ”Worklets och kodkörning på UI-tråden” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen React Native Academy, inklusive ”Worklets och kodkörning på UI-tråden”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i React Native Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Worklets och kodkörning på UI-tråden”?
Markera funktioner som worklets med direktivet 'worklet', förstå varför detta kringgår JS-bryggan och skriv gesthanterare som uppdaterar delade värden direkt. Ni övar på React Native Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig React Native Academy?
Du behöver inga förkunskaper. Utbildningen i React Native Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”Worklets och kodkörning på UI-tråden”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här React Native Academy-lektionen?
Ja. Varje React Native Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Installera Reanimated och delade värden
- Worklets och kodkörning på UI-tråden
- Pan- och svepgester med Gesture Handler
- Nyp för att zooma och rotera