React Native Academy · leksjon

Worklets og kjøring av kode på UI-tråden

Merk funksjoner som worklets med 'worklet'-direktivet, forstå hvorfor dette omgår JS-broen, og skriv gesture handlers som oppdaterer delte verdier direkte.

Leksjon 2 av 413 trinn

Worklets og kjøring av kode på UI-tråden er en gratis leksjon i React Native Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i React Native Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i React Native Academy inneholder totalt 4 leksjoner.

Hva er en worklet?

En worklet er en JavaScript-funksjon som Reanimated kjører på UI-tråden i stedet for JavaScript-tråden. Reanimateds Babel-plugin finner funksjoner som er merket med direktivstrengen 'worklet' øverst i funksjonskroppen, og omformer dem ved bygging til et format som kan sendes til og kjøres på UI-tråden.

Worklets er den sentrale mekanismen som gjør det mulig for Reanimated å behandle gestdata og oppdatere animasjoner bilde for bilde med 60 bilder per sekund, uten å involvere JavaScript-tråden eller bridgen. De er den viktigste arkitektoniske nyvinningen som skiller Reanimated fra det klassiske 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

Direktivet «worklet»

Strengliteralen 'worklet' øverst i funksjonskroppen er et spesialdirektiv – omtrent som 'use strict'. Reanimateds Babel-plugin leter etter det og omformer funksjonen slik at den kan serialiseres og kjøres på UI-tråden. Uten dette direktivet vil et kall til funksjonen fra en worklet-kontekst bli utført stille på JS-tråden, noe som kan føre til krasj eller feilaktig oppførsel.

Funksjoner som sendes til Reanimated-hooks som useAnimatedStyle, behandles automatisk som worklets selv uten direktivet. Vanlige hjelpefunksjoner som kalles FRA disse hookene, trenger direktivet eksplisitt.

// 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;
}

Hvorfor UI-tråden er viktig for gester

Berøringshendelser på mobile enheter behandles på UI-tråden. Når en bruker drar en finger, genererer enheten berøringshendelser mange ganger per sekund (opptil 120 bilder per sekund på moderne enheter). Hvis gesthåndteringen krevde JavaScript-tråden, måtte hver berøringshendelse krysse bridgen, noe som ville introdusere forsinkelse og gjøre samhandlingen treg og lite responsiv.

Med worklets kjører både gestbehandleren og animasjonsresponsen på UI-tråden. Oppdateringene av den animerte verdien skjer i samme trådsyklus som berøringshendelsen, noe som gir en reell gestrespons uten forsinkelse og føles som innebygde interaksjoner på iOS og Android.

Kalle worklets fra animerte behandlere

Reanimated tilbyr hooks som useAnimatedScrollHandler og useAnimatedGestureHandler, der tilbakekallene kjører som worklets på UI-tråden. Inne i disse tilbakekallene kan De kalle enhver funksjon som er merket med 'worklet', direkte, og lese og skrive delte verdier ved hjelp av .value.

Å skrive til en delt verdi inne i et gesttilbakekall er måten De får en animert komponent til å følge brukerens finger i sanntid på – skrivingen skjer på UI-tråden, og den animerte stilen reagerer umiddelbart.

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

const scrollY = useSharedValue(0);

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

runOnJS: Kalle React fra worklets

Worklets kjører på UI-tråden og kan ikke kalle React-funksjoner, setState eller navigasjonsmetoder direkte. Når De trenger å utløse kode på JavaScript-tråden fra en worklet (for eksempel oppdatere React-tilstand eller navigere etter at en gest er fullført), kan De bruke runOnJS.

runOnJS(fn)(args) planlegger funksjonen for kjøring på JS-tråden i neste tilgjengelige bilde. Dermed kan gestbehandlere oppdatere React-tilstand eller kalle navigasjon etter en interaksjon uten å bryte worklet-kjøringsmodellen.

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: Kalle worklets fra JS-tråden

Det motsatte av runOnJS er runOnUI. Dette lar Dem planlegge en worklet-funksjon for kjøring på UI-tråden fra JavaScript-tråden. Det er nyttig for å utløse animasjoner fra hendelsesbehandlere på JS-tråden (for eksempel ved knappetrykk), samtidig som selve animasjonslogikken forblir i en worklet.

I de fleste tilfeller holder det å tilordne til sharedValue.value (som allerede kjører på UI-tråden), så runOnUI er mindre vanlig å trenge. Det blir nødvendig når De må gruppere flere operasjoner på UI-tråden atomisk.

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 });
  })();
}

Begrensninger ved worklets

Worklets er ikke fullverdig JavaScript – de kjører i et begrenset miljø som ikke har tilgang til Node.js-API-er, React-hooks, komponenttilstand eller hele JavaScript-kjøremiljøet. De kan ikke bruke console.log fra en worklet i produksjon (det gjør ingenting). De kan heller ikke importere tredjepartsmoduler inne i en worklet med mindre modulene uttrykkelig støtter Reanimated.

Hold worklets konsentrert om matematikk og beregning av verdier: begrensning av verdier, avbildning av intervaller, beregning av fysikk og lesing av gestdata. Flytt alt annet til JS-tråden ved hjelp 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 for å overvåke verdier

useAnimatedReaction lar Dem overvåke en delt verdi eller et avledet uttrykk og kjøre en worklet (eller kalle tilbake til JS) når verdien endres. Den tar to worklet-funksjoner: en prepare-funksjon som leser verdier, og en reaction-funksjon som mottar gjeldende og tidligere verdier.

Dette er nyttig for å utløse bivirkninger når en animasjon når en terskel – for eksempel ved å kalle navigasjon for å lukke en skjerm når et forskyvningsmål overstiger 50 % av skjermhøyden.

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 beregnede delte verdier

useDerivedValue oppretter en ny delt verdi som automatisk beregnes ut fra andre delte verdier. Avledningsfunksjonen er en worklet som kjører på UI-tråden hver gang en av avhengighetene endres. Den tilsvarer Reanimated-versjonen av useMemo, men for delte verdier.

Bruk avledede verdier til å beregne komplekse transformasjoner én gang (i stedet for å gjenta matematikken i hver useAnimatedStyle), eller til å styre flere stil-hooks fra én felles kilde.

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 praksis: Parallakse ved rulling

Et parallaksehode ved rulling viser worklets i praksis. Rulleforskyvningen styrer flere avledede verdier – et bakgrunnsbilde beveger seg med halv hastighet, en tittel tones ut, og en klebrig minitopptekst tones inn. Alle disse avledningene kjører som worklets utløst av rullesporingen i Animated.event.

Hele parallakseffekten kjører med 60 bilder per sekund uten involvering av JavaScript-tråden, fordi hvert trinn – rullesporing, verdiavledning og stilberegning – er 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,
}));

Feilsøking av worklets

Det er vanskeligere å feilsøke worklets enn vanlig JavaScript fordi de kjører på en separat tråd. Bruk console.log inne i worklets under utvikling (det fungerer i feilsøkingsmodus via Hermes), og bruk useAnimatedReaction med runOnJS(console.log) for logging som er trygg i produksjon.

Reanimated integreres også med React DevTools Profiler for å visualisere hvilke worklets som kjører. Hvis animasjonene oppfører seg uventet, kan De legge til en useDerivedValue for å logge den beregnede verdien for hvert bilde og finne ut hvor beregningen avviker fra forventningene.

// 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)
);

Kort sjekk

Test forståelsen Deres av konseptene innen React Native Mobile Development fra denne leksjonen.

Oppsummering av leksjonen

I denne leksjonen har De lært at worklets er funksjoner merket med direktivet «worklet» som kjører på UI-tråden utenom bridgen, at runOnJS planlegger kall på JS-tråden fra worklets for React-tilstand og navigasjon, og at useDerivedValue og useAnimatedReaction lar Dem avlede og overvåke delte verdier i en worklet-kontekst. Neste tema er å bygge et kort som kan dras, ved hjelp av Pan-gester med React Native Gesture Handler.

Gratis å komme i gang

Lær deg JavaScript med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
30
Leksjoner
120

Ofte stilte spørsmål

Er leksjonen «Worklets og kjøring av kode på UI-tråden» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien React Native Academy, inkludert «Worklets og kjøring av kode på UI-tråden», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i React Native Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Worklets og kjøring av kode på UI-tråden»?

Merk funksjoner som worklets med 'worklet'-direktivet, forstå hvorfor dette omgår JS-broen, og skriv gesture handlers som oppdaterer delte verdier direkte. Du øver på React Native Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med React Native Academy?

Ingen tidligere erfaring er nødvendig. React Native Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Worklets og kjøring av kode på UI-tråden»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne React Native Academy-leksjonen?

Ja. Alle React Native Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Installere Reanimated og delte verdier
  2. Worklets og kjøring av kode på UI-tråden
  3. Panorerings- og sveipebevegelser med Gesture Handler
  4. Knip-for-å-zoome og rotere
← Tilbake til React Native Academy