Upřímně, Reanimated 4 byl pro mě jedním z nejvýraznějších přelomů, co jsem v React Native ekosystému za posledních pár let zažil. V roce 2025 vyšel a v roce 2026 už je to prostě defaultní volba pro plynulé 120 FPS animace nad Fabric architekturou. Pokud spravujete app postavenou na trojce nebo přemýšlíte, jak se vyhnout té otravné chybě „duplicate worklet instances" a propadům FPS u dlouhých seznamů, tenhle průvodce vás provede krok za krokem – od instalace až po pokročilou optimalizaci.
Co je nového v Reanimated 4
Reanimated 4 není jen verze s lepším výkonem. Je to spíš architektonický restart knihovny. Tady jsou hlavní změny, na které si dejte pozor:
- Vyžaduje New Architecture (Fabric + TurboModules). Stará architektura už není podporována, což zjednodušuje interní kód, ale vynucuje migraci – ať chcete, nebo ne.
- Worklety se odstěhovaly do samostatného balíčku
react-native-worklets. Babel plugin teď žije tam, ne v Reanimated (a tohle je mimochodem zdroj asi 80 % chyb při migraci). - Nové deklarativní CSS-kompatibilní API – animace a tranzice se dají psát stylem známým z webu (
transition,animationproperty veStyleSheet). - Nové runtime API:
runOnRuntimeSync,runOnRuntimeAsync,scheduleOnRuntimeWithIdpro multi-runtime scénáře (worker thread, audio thread). - Shareable typ s C++ bindings – stabilní sdílená paměť mezi JS a UI runtime.
- Energy-based physics – spring animace se ukončují podle skutečné energie systému, ne podle nějakého libovolného epsilonu. Konečně.
Pokud jste minuli související přechod Reactu, mrkněte se nejdřív na Novou architekturu React Native v roce 2026 – Reanimated 4 na ní staví přímo.
Předpoklady a kompatibilita
K květnu 2026 platí tohle:
- React Native 0.78+ (poslední tři minor verze)
- Expo SDK 53+
- Zapnutá New Architecture (
newArchEnabled=truevapp.json/ Gradle / Podfile) - Node 20+, Hermes engine
- Xcode 16, Android Gradle Plugin 8.5+
Kompatibilní matice
Reanimated 4.2.x ↔ RN 0.78–0.80 ↔ Worklets 0.6.x ↔ Expo SDK 53+
Reanimated 4.1.x ↔ RN 0.76–0.78 ↔ Worklets 0.5.x ↔ Expo SDK 52
Reanimated 3.16.x ↔ RN 0.74–0.76 (poslední 3.x – LTS do konce 2026)
Instalace v novém projektu (Expo)
Začneme tím jednodušším scénářem – nový projekt na zelené louce:
npx create-expo-app@latest moje-aplikace --template default
cd moje-aplikace
npx expo install react-native-reanimated react-native-worklets
Otevřete babel.config.js a přidejte plugin z balíčku worklets (ne z Reanimated – tohle bývala asi nejčastější chyba při migraci):
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['react-native-worklets/plugin'],
};
};
Plugin musí být poslední v seznamu. Tečka. V metro.config.js pak nepotřebujete nic dalšího – Reanimated 4 si Metro detekuje automaticky.
Migrace z Reanimated 3 na 4
Migrace je v drtivé většině případů API-kompatibilní, ale je tu pár bodů, které vás zaručeně chytí. Tady jsou:
1. Přesun Babel pluginu
V babel.config.js jednoduše nahraďte:
// PŘEDTÍM (Reanimated 3)
plugins: ['react-native-reanimated/plugin']
// NYNÍ (Reanimated 4)
plugins: ['react-native-worklets/plugin']
Zapomenutí na tuhle změnu se projeví jako runtime error ReanimatedError: Tried to synchronously call a non-worklet function on the UI thread. Mně osobně to zabralo asi hodinu googlení, než mi došlo, co je špatně. Ušetřete si to.
2. Zapnutí New Architecture
V app.json (Expo) nebo android/gradle.properties + ios/Podfile musíte explicitně povolit:
{
"expo": {
"newArchEnabled": true
}
}
Bez tohohle Reanimated 4 neproběhne ani build – Pod install hlásí Reanimated 4 requires New Architecture.
3. Vyčištění caches po upgrade
Tohle vypadá brutálně, ale věřte mi – ušetří vás to hodin debugu:
rm -rf node_modules ios/Pods ios/build android/build android/app/build
watchman watch-del-all
npm install
cd ios && pod install && cd ..
npx expo start --clear
4. Drobné API přejmenování
useAnimatedGestureHandlerje oficiálně deprecated – přejděte nareact-native-gesture-handlerv3+ aGesture.Pan()API.useDerivedValueteď vyžaduje, aby vrátil hodnotu synchronně; asynchronní derivace selže s warningem.
Základní animace: shared values a animované styly
Pokud jste s Reanimated zatím nepracovali, jádro stojí na třech konceptech:
useSharedValue– stav, který žije na UI threadu a JS o něm ví.useAnimatedStyle– worklet, který z shared values počítá style props.withSpring / withTiming / withDecay– wrappery, které ze surových hodnot dělají časované přechody.
Klasický příklad – tlačítko, které pulsuje při stisku:
import { Pressable, StyleSheet, Text } from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
export function PulseButton() {
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
return (
<Pressable
onPressIn={() => (scale.value = withSpring(0.92))}
onPressOut={() => (scale.value = withSpring(1))}
>
<Animated.View style={[styles.button, animatedStyle]}>
<Text style={styles.label}>Stisknout</Text>
</Animated.View>
</Pressable>
);
}
const styles = StyleSheet.create({
button: { padding: 16, backgroundColor: '#4f46e5', borderRadius: 12 },
label: { color: 'white', fontWeight: '600', textAlign: 'center' },
});
Nové CSS-kompatibilní API: kdy ho použít
Reanimated 4 přinesl deklarativní stylovou variantu, která vypadá takřka stejně jako CSS na webu. Hodí se pro jednoduché tranzice a stavem řízené animace, kde nepotřebujete gestura ani fyziku.
import Animated from 'react-native-reanimated';
import { useState } from 'react';
import { Pressable, StyleSheet } from 'react-native';
export function ExpandingCard() {
const [open, setOpen] = useState(false);
return (
<Pressable onPress={() => setOpen((p) => !p)}>
<Animated.View
style={[
styles.card,
{
height: open ? 220 : 80,
backgroundColor: open ? '#0ea5e9' : '#1e293b',
transitionProperty: ['height', 'backgroundColor'],
transitionDuration: '300ms',
transitionTimingFunction: 'ease-out',
},
]}
/>
</Pressable>
);
}
const styles = StyleSheet.create({
card: { borderRadius: 16, marginHorizontal: 16 },
});
CSS API vs. worklet API
| Kritérium | CSS API | Worklet API |
|---|---|---|
| Závisí na gestu | Ne | Ano |
| Reakce na props/stav | Vynikající | Vyžaduje víc boilerplate |
| Fyzika (spring, decay) | Omezená | Plná |
| Bundle velikost | Menší | Stejná |
| Výkon | Stejný – obojí běží na UI threadu | Stejný |
Pravidlo palce (které mi za poslední rok ušetřilo spoustu nervů): pokud animaci spouští stav komponenty (boolean, číslo z propsy), pište CSS API. Pokud ji řídí gesture nebo scroll position, držte se worklet API.
Gestura s Gesture Handler v3
Drag-to-dismiss bottom sheet s pružinovým návratem – kanonický příklad propojení gestur a Reanimated:
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
export function Draggable() {
const translateY = useSharedValue(0);
const pan = Gesture.Pan()
.onChange((e) => {
translateY.value += e.changeY;
})
.onEnd((e) => {
if (Math.abs(e.velocityY) > 800) {
translateY.value = withSpring(e.velocityY > 0 ? 600 : -600, {
velocity: e.velocityY,
});
} else {
translateY.value = withSpring(0);
}
});
const style = useAnimatedStyle(() => ({
transform: [{ translateY: translateY.value }],
}));
return (
<GestureDetector gesture={pan}>
<Animated.View style={[{ width: 240, height: 240, backgroundColor: '#10b981', borderRadius: 24 }, style]} />
</GestureDetector>
);
}
Layout animace a entering/exiting tranzice
Reanimated 4 zachovává prediktivní layout API. Pro připnutí/odebrání položek ze seznamu stačí pár řádek:
import Animated, { FadeIn, FadeOut, Layout } from 'react-native-reanimated';
<Animated.View
entering={FadeIn.duration(220)}
exiting={FadeOut.duration(160)}
layout={Layout.springify().damping(14)}
/>
V Reanimated 4 byly tyhle presety přepsány tak, aby běžely čistě v Fabric C++ vrstvě. Díky tomu jsou znatelně levnější u dlouhých seznamů – a u FlashListu s 5000+ položkami to opravdu poznáte.
Optimalizace výkonu: 120 FPS bez kompromisů
Reanimated 4 cílí na 120 FPS displeje (ProMotion, většina Androidu high-end). Ale to neznamená, že je dostanete zdarma. Tady jsou nejčastější brzdy, na které jsem v praxi narazil:
1. Propady FPS u FlatList / FlashList
Pokud při scrollu animujete položky individuálně (například shimmer placeholder), zapněte independent scroll a zabalte styly:
<FlashList
data={items}
renderItem={renderRow}
removeClippedSubviews
drawDistance={250}
estimatedItemSize={72}
/>
A v renderRow používejte useAnimatedStyle jen pro transform a opacity. Animace width, height nebo backgroundColor vynutí relayout – a 120 FPS zapomeňte.
2. Vyhněte se runOnJS v hot pathu
Každé volání runOnJS přepíná thread. V onChange gestur ho fakt nepoužívejte – přesuňte logiku do worklet vrstvy a JS volejte až v onEnd.
3. Měřte přes nový Reanimated Profiler
import { startProfiling, stopProfiling } from 'react-native-reanimated';
startProfiling();
// ...interakce...
const report = await stopProfiling();
console.log(report.uiThreadFps, report.jsThreadFps);
Multi-runtime: práce s worker threadem
Nové runtime API umožňuje rozjet těžkou výpočetní práci mimo UI a JS thread. Tohle byla pro mě jedna z hlavních věcí, na které jsem se z Reanimated 4 těšil:
import { createWorkletRuntime, runOnRuntimeAsync } from 'react-native-worklets';
const heavyRuntime = createWorkletRuntime('image-processor');
async function processImage(buffer) {
return await runOnRuntimeAsync(heavyRuntime, (data) => {
'worklet';
// CPU-náročná transformace
return transform(data);
})(buffer);
}
Použitelné pro real-time obraz, audio buffery nebo parsování velkých JSONů bez blokování UI.
Časté chyby a jejich řešení
„Duplicate worklet instances"
Vzniká, když máte v projektu jak react-native-reanimated/plugin, tak react-native-worklets/plugin. Smažte ten starý a vyčistěte cache:
npx expo start --clear
„Reanimated 4 requires New Architecture"
Zkontrolujte app.json, android/gradle.properties (newArchEnabled=true) a ios/Podfile (:fabric_enabled => true).
Animace nereaguje, žádná chyba
Téměř vždy chybí Babel plugin nebo není poslední v poli pluginů. A ověřte, že animovaný komponent je <Animated.View>, ne obyčejný <View> – to je klasika, na kterou každý jednou narazí.
Srovnání s Moti, Framer Motion a Skia
| Knihovna | Hodí se na | Závisí na Reanimated? |
|---|---|---|
| Reanimated 4 | Univerzální nízko-úrovňový základ | — |
| Moti | Deklarativní zápis tranzic, prototypy | Ano (wrap nad Reanimated) |
| React Native Skia | Vlastní vykreslování, canvas, shadery | Doplňuje (ne nahrazuje) |
| Lottie | After Effects exporty, ikonové animace | Ne |
V roce 2026 je běžný stack tenhle: Reanimated 4 + Gesture Handler v3 pro interakce, Skia pro vlastní vykreslování a Lottie pro statické vektorové animace z designerského pipeline. Funguje to dobře a moc bych si nevymýšlel.
FAQ
Jak migrovat z Reanimated 3 na Reanimated 4?
Zapněte New Architecture, nainstalujte react-native-worklets, v babel.config.js nahraďte react-native-reanimated/plugin za react-native-worklets/plugin a vyčistěte všechny cache (node_modules, Pods, Gradle build, Metro). API komponent zůstává v 95 % případů identické.
Funguje Reanimated 4 na staré architektuře React Native?
Ne. Reanimated 4 vyžaduje Fabric a TurboModules. Pokud aplikaci ještě nemůžete migrovat, zůstaňte na Reanimated 3.16 LTS – bude podporován minimálně do konce roku 2026.
Kdy použít CSS API a kdy klasické worklety?
CSS API zvolte u animací řízených stavem komponenty (boolean, prop). Worklet API použijte u všeho, co reaguje na gesto, scroll position nebo potřebuje fyziku (spring, decay).
Je react-native-worklets povinná závislost?
Ano. Reanimated 4 worklety neobsahuje – jsou v samostatném balíčku, který obsluhuje Babel plugin i runtime infrastrukturu. Bez něj projekt nesestaví.
Proč při scrollování FlatListu padají FPS u animovaných řádků?
Nejčastější příčinou je animace layout-vlastností (width, height, margin), která spouští relayout celého seznamu. Držte se animací transform a opacity, používejte FlashList s pevným estimatedItemSize a vyhněte se runOnJS v každém framu.
Závěr
Reanimated 4 představuje technologický skok, který platí daň v podobě povinné migrace na New Architecture. Ale výměnou nabízí stabilní 120 FPS, multi-runtime možnosti a deklarativní CSS API – a to za to podle mě stojí. Pokud začínáte nový projekt v roce 2026, jděte rovnou do Reanimated 4. Pokud spravujete legacy 3.x kód, plánujte migraci v rámci širšího přechodu na Fabric – obě změny můžete udělat současně a ušetřit si dva oddělené retesty.