
React Native Reanimated - wprowadzenie do płynnych i wydajnych animacji w aplikacjach mobilnych
Chcesz tworzyć płynne, responsywne animacje w React Native, które naprawdę wyglądają i działają jak natywne? Poznaj React Native Reanimated — potężną bibliotekę do animacji działającą poza wątkiem JavaScript. W tym artykule krok po kroku wyjaśniamy, jak działa, kiedy warto jej używać i jak zacząć tworzyć nowoczesne, wydajne interfejsy mobilne z użyciem Reanimated.

Co to jest React Native Reanimated?
React Native Reanimated to zaawansowana biblioteka do tworzenia wydajnych, natywnych animacji w aplikacjach zbudowanych na React Native. Została opracowana i jest rozwijana przez Software Mansion – polską firmę specjalizującą się w tworzeniu narzędzi dla środowiska React Native, która stoi również za takimi projektami jak react-native-gesture-handler
czy react-native-screens
.
Kiedy i dlaczego warto używać React Native Reanimated?
React Native Reanimated sprawdza się najlepiej wtedy, gdy zależy nam na płynnych, responsywnych animacjach, które nie zawodzą nawet w bardziej złożonych interfejsach użytkownika. W przeciwieństwie do standardowego API Animated
, Reanimated działa na natywnym wątku UI, co oznacza, że animacje nie są zależne od wydajności JavaScriptu.
Dzięki temu:
- animacje nie przycinają się, nawet gdy aplikacja wykonuje intensywne operacje w tle,
- możemy bezproblemowo łączyć je z gestami (np. przeciągnięcia, przesunięcia, dociągnięcia),
- zapewniają doświadczenie użytkownika zbliżone do natywnych aplikacji,
- sprawdzają się w komponentach takich jak bottom sheets, carousels, swipeable lists, drag & drop i wielu innych.
Warto sięgnąć po Reanimated, gdy:
- klasyczne
Animated
zaczyna się dławić lub jest trudne do rozbudowy, - zależy Ci na nowoczesnym, płynnym UI (np. animacje ekranów, przejść, modali),
- tworzysz interfejsy silnie zależne od gestów i dotyku.
To narzędzie stworzone z myślą o aplikacjach, które mają „czuć się” jak natywne — niezależnie od platformy.
Podstawowe pojęcia i koncepcje
Aby skutecznie korzystać z React Native Reanimated, warto zrozumieć kilka kluczowych koncepcji, które odróżniają tę bibliotekę od standardowego podejścia w React Native:
1. useSharedValue
To specjalny typ wartości, który żyje poza wątkiem JavaScript i jest współdzielony z natywnym UI. Używamy go do przechowywania zmiennych, które będą animowane (np. pozycja, skala, przezroczystość).
const opacity = useSharedValue(0);
2. useAnimatedStyle
Hook, który pozwala przypisać animowane wartości do stylu komponentu. Łączy się z shared value
, aby dynamicznie aktualizować styl bez przeładowywania komponentu.
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value,
}));
3. Worklets
Worklety to funkcje oznaczone jako "worklet"
, które są uruchamiane poza głównym wątkiem JS — bezpośrednio na natywnym silniku (np. Hermes). To klucz do płynnych animacji, które nie zależą od wydajności JavaScriptu.
runOnUI(() => {
'worklet';
sharedValue.value = withSpring(1);
})();
4. Animatory: withTiming
, withSpring
, withDelay
Reanimated oferuje gotowe metody animacji wartości:
withTiming
– animacja liniowa w czasie (np. do przezroczystości),withSpring
– animacja sprężynowa z fizyką (idealna do przesunięć),withDelay
,withSequence
,withRepeat
– kombinacje animacji dla złożonych efektów.
5. runOnUI
i runOnJS
Te funkcje umożliwiają komunikację między natywnym wątkiem animacji a logiką JavaScript:
runOnUI()
– uruchamia funkcję po stronie UI (np. przy starcie animacji),runOnJS()
– pozwala z natywnego kontekstu wywołać JS (np. callback po zakończeniu animacji).
6. useDerivedValue
Tworzy wartość zależną od innych wartości współdzielonych, automatycznie aktualizując się przy ich zmianie.
const derived = useDerivedValue(() => {
return sharedValue.value * 2;
});
7. useAnimatedReaction
Reaguje na zmiany wartości współdzielonych, umożliwiając wykonywanie efektów ubocznych w odpowiedzi na te zmiany.
useAnimatedReaction(
() => sharedValue.value,
(newValue, oldValue) => {
// reakcja na zmianę wartości
}
);
8. useAnimatedGestureHandler
Integruje gesty z animacjami, umożliwiając płynne interakcje użytkownika z interfejsem.
const gestureHandler = useAnimatedGestureHandler({
onStart: (event, context) => {
// gest rozpoczęty
},
onActive: (event, context) => {
// gest aktywny
},
onEnd: (event, context) => {
// gest zakończony
},
});
9. interpolate
i interpolateColor
Funkcje do przekształcania wartości z jednego zakresu na inny, często używane do tworzenia płynnych przejść.
const animatedStyle = useAnimatedStyle(() => {
return {
opacity: interpolate(sharedValue.value, [0, 1], [0.5, 1]),
};
});
Jak zainstalować i skonfigurować React Native Reanimated?
Jest to bardzo proste i nie sprawi Ci większych problemów. Musisz poprawnie zainstalować bibliotekę i skonfigurować projekt. Poniżej znajdziesz kroki potrzebne do uruchomienia Reanimated w typowej aplikacji React Native.
1. Aby zainstalowć React Native Reanimated uruchom w terminalu:
npm install react-native-reanimated
Jeśli korzystasz z Expo, pamiętaj, że Reanimated jest już częścią SDK, ale musisz upewnić się, że masz odpowiednią wersję.
2. Następnie w pliku babel.config.js
koniecznie dodaj plugin Reanimated na końcu listy pluginów:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin'], // <-- musi być ostatni!
};
Tworzymy pierwszą animację – płynne pojawienie się i powiększenie komponentu
Skoro już wiesz jak zainstalować bibliotekę, teraz stworzymy komponent, który przy wejściu płynnie się pojawia i lekko się powiększa. Takie animacje są bardzo często używane w prawdziwych aplikacjach — np. do prezentowania kart produktów, banerów powitalnych, powiadomień czy ekranów onboardingowych.
import React, { useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
} from 'react-native-reanimated';
export default function IntroCard() {
const opacity = useSharedValue(0);
const scale = useSharedValue(0.8);
useEffect(() => {
opacity.value = withTiming(1, { duration: 800 });
scale.value = withTiming(1, { duration: 800 });
}, []);
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{ scale: scale.value }],
}));
return (
<Animated.View style={[styles.card, animatedStyle]}>
<Text style={styles.text}>Witaj w Reanimated 🎉</Text>
</Animated.View>
);
}
const styles = StyleSheet.create({
card: {
backgroundColor: '#ffffff',
padding: 20,
margin: 20,
borderRadius: 12,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
elevation: 5,
alignItems: 'center',
},
text: {
fontSize: 18,
fontWeight: '600',
},
});
Co tu sie dzieję?
Przygotowanie wartości do animacji
const opacity = useSharedValue(0);
const scale = useSharedValue(0.8);
Co to robi?
Tworzymy tzw. „shared values”, czyli specjalne zmienne, które będą się zmieniać podczas animacji — ale bez wpływu na główny wątek Reacta. opacity
kontroluje przezroczystość, a scale
odpowiada za rozmiar.
Następnie uruchamiamy animacje po pojawieniu się komponentu:
useEffect(() => {
opacity.value = withTiming(1, { duration: 800 });
scale.value = withTiming(1, { duration: 800 });
}, []);
Dlaczego tak?
Używamy withTiming
, żeby płynnie zmieniać wartości w czasie. opacity
rośnie od 0 do 1 (komponent staje się widoczny), a scale
od 0.8 do 1 (lekki efekt „powiększenia”).
Tworzymy styl animowany:
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{ scale: scale.value }],
}));
Ten styl będzie się dynamicznie aktualizował razem z naszymi shared values
. Działa to jak „magia” — bez żadnego setState
, bez migania, bez spowalniania aplikacji.
Zastosowanie animowanego komponentu:
<Animated.View style={[styles.card, animatedStyle]}>
<Text style={styles.text}>Witaj w Reanimated 🎉</Text>
</Animated.View>
Używamy Animated.View
, bo tylko on potrafi zrozumieć animowane style. Sam Text
się nie animuje — tylko kontener, w którym się znajduje.
Reanimated vs Animated – dlaczego warto przesiąść się na nowoczesne podejście?
React Native od początku oferuje bibliotekę Animated
, która pozwala tworzyć animacje w aplikacjach. Jednak wraz ze wzrostem oczekiwań użytkowników i potrzebą lepszej wydajności, wiele zespołów zaczęło szukać bardziej elastycznego rozwiązania. Tak powstał React Native Reanimated – narzędzie, które zrywa z ograniczeniami starego podejścia.
1. WydajnośćAnimated
działa na wątku JavaScript, co oznacza, że każda animacja przechodzi przez bridge JS-Native. W praktyce prowadzi to do opóźnień, zwłaszcza jeśli aplikacja jest mocno obciążona. Z kolei Reanimated wykonuje animacje bezpośrednio na natywnym wątku UI, co daje płynność porównywalną z aplikacjami mobilnymi pisanymi w Swift czy Kotlinie.
2. API i styl kodowaniaAnimated
opiera się na podejściu imperatywnym — musimy stworzyć zmienną animacyjną (new Animated.Value()
), zainicjować ją, a potem „ręcznie” uruchomić animację za pomocą .start()
. W Reanimated pracujemy w sposób deklaratywny: używamy hooków takich jak useSharedValue
czy useAnimatedStyle
, co czyni kod bardziej czytelnym i logicznym, szczególnie w dużych projektach.
3. Re-renderowanie komponentówAnimated
często wymaga dodatkowych trików, aby animować komponenty bez ich ciągłego przeładowywania. Reanimated nie potrzebuje re-renderów – wszystkie wartości żyją poza Reactem i są aktualizowane w tle, co wpływa pozytywnie na wydajność i stabilność.
4. Obsługa gestów
Z Animated
animowanie w reakcji na gesty (np. przeciąganie palcem) bywa trudne i nieintuicyjne. W przypadku Reanimated, dzięki ścisłej integracji z react-native-gesture-handler
, obsługa gestów jest naturalna i bardzo precyzyjna. Można tworzyć złożone interakcje z płynnością natywnej aplikacji.
5. Elastyczność i możliwości
Reanimated daje dostęp do zaawansowanych narzędzi jak withSpring
, withSequence
, withDelay
, interpolate
, useDerivedValue
, czy runOnJS
. Takiej elastyczności nie oferuje żadne inne API do animacji w React Native. W porównaniu z tym, Animated
wypada dość sztywno i wymaga więcej pracy przy złożonych przypadkach użycia.
6. Wsparcie i rozwójAnimated
to starsze API, obecne w React Native od dawna, ale obecnie rozwijane bardzo powoli. Reanimated to aktywny, nowoczesny projekt rozwijany przez Software Mansion, wspierany przez dużą społeczność i wykorzystywany w wielu topowych aplikacjach mobilnych.
Przykład – animacja opacity w obu podejściach:
Animated:
Animated.timing(animatedValue, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}).start();
Trzeba osobno tworzyć referencję (new Animated.Value(0)
), dbać o start()
, i martwić się o useNativeDriver
.
Reanimated:
opacity.value = withTiming(1, { duration: 500 });
Najczęstsze błędy i pułapki
Reanimated to potężna biblioteka, ale jak każde narzędzie – ma swoje niuanse. Zwłaszcza na początku łatwo popełnić kilka typowych błędów, które mogą prowadzić do frustracji i nieoczywistych błędów w działaniu aplikacji. Oto lista najczęstszych problemów oraz ich przyczyn:
1. Brak pluginu w babel.config.js
Najczęstszy klasyk – zapomnienie o dodaniu "react-native-reanimated/plugin"
w pliku babel.config.js
. Plugin musi być ostatni na liście pluginów — inaczej kod z worklet
nie zostanie przetworzony poprawnie.
plugins: ['react-native-reanimated/plugin'] // <-- ostatni!
2. Nieprawidłowe komponenty (np. View
zamiast Animated.View
)
Jeśli próbujesz użyć useAnimatedStyle
na zwykłym View
, nic się nie stanie — styl animowany musi być przypisany do komponentu z przestrzeni Animated
.
Poprawnie:
<Animated.View style={animatedStyle} />
Niepoprawnie:
<View style={animatedStyle} /> // Nie zadziała!
3. Użycie setState
wewnątrz worklet
Worklety działają poza Reactem, więc nie można w ich wnętrzu używać funkcji takich jak setState()
czy console.log()
bez użycia runOnJS
. Jeśli musisz uruchomić coś w świecie JS z poziomu worklet
, użyj:
runOnJS(setState)(nowaWartosc);
4. Próba animowania stylu, który nie obsługuje natywnego drivery
Nie wszystkie style mogą być animowane w Reanimated (np. zIndex
, flexGrow
, fontWeight
— w niektórych wersjach). Zawsze warto przetestować animację krok po kroku i używać tylko wspieranych właściwości.
5. Zapominanie o value
W przypadku sharedValue
, musisz odwoływać się do .value
– to najczęściej pomijany szczegół przez osoby uczące się Reanimated.
Poprawnie:
opacity.value = withTiming(1); // ✅
Dlaczego React Native Reanimated to coś więcej niż tylko „ładne” animacje?
Na pierwszy rzut oka React Native Reanimated może wydawać się tylko biblioteką do upiększania interfejsów. Tymczasem jego rola w aplikacji mobilnej wykracza daleko poza samą estetykę. W nowoczesnym mobile app development – animacje nie są jedynie dodatkiem wizualnym — pełnią funkcję informacyjną, organizacyjną i emocjonalną. I to właśnie Reanimated pozwala je realizować w sposób, który jest zarówno technicznie wydajny, jak i projektowo świadomy.
Dobrze zaprojektowane animacje ułatwiają zrozumienie kontekstu aplikacji: pokazują relacje między elementami, informują o zmianie stanu, prowadzą użytkownika przez kolejne kroki i nadają rytm interakcji. Zamiast zaskakujących przejść czy nagłych zmian w układzie, użytkownik dostaje płynny, spójny flow, który wzmacnia poczucie kontroli i intuicyjności. Reanimated pozwala na bardzo precyzyjne odwzorowanie takich mikrointerakcji — bez lagów, z pełną kontrolą nad gestami i animacjami.
Z perspektywy technicznej, Reanimated to również narzędzie architektoniczne. Przeniesienie logiki animacji na natywny wątek pozwala znacząco odciążyć główny wątek JavaScript, co ma ogromne znaczenie przy rozbudowanych ekranach, asynchronicznych danych, gestach i scrollach. W aplikacjach, które muszą działać płynnie na urządzeniach średniej klasy, taka separacja logiki to wręcz warunek konieczny.
Reanimated daje też możliwość pisania interfejsu w sposób deklaratywny, spójny i łatwy do testowania. Tworzenie animacji nie wymaga już osobnego zarządzania stanem komponentu czy wymyślania workarounds. Logika zachowania komponentu może być zapisana jako czyste, deterministyczne funkcje oparte na sharedValue
, useDerivedValue
czy interpolate
. To czyni kod prostszym, bardziej czytelnym i łatwiejszym w utrzymaniu.
Dlatego właśnie Reanimated nie powinien być traktowany wyłącznie jako biblioteka „ładnych efektów”. To pełnoprawne narzędzie inżynierskie i UX-owe, które pozwala projektować interfejsy bardziej świadomie — z naciskiem na użyteczność, wydajność i przewidywalność. W nowoczesnym świecie aplikacji mobilnych to nie tylko przewaga. To standard.
Rekomendowane źródła nauki
Jeśli chcesz lepiej zrozumieć potencjał Reanimated i pogłębić wiedzę, warto sięgnąć po kilka sprawdzonych źródeł, które pomogą Ci krok po kroku, np.: https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/, https://github.com/software-mansion/react-native-reanimated
FAQ – najczęściej zadawane pytania
1. Czy mogę używać Reanimated z Expo?
Tak, Reanimated działa z Expo, ale pełne wsparcie (zwłaszcza dla gestów i niektórych funkcji natywnych) dostępne jest od SDK 46 wzwyż. Upewnij się, że masz aktualną wersję Expo i odpowiednio skonfigurowany plugin Babel.
2. Czy Reanimated działa z React Navigation?
Tak, i to bardzo dobrze. Reanimated jest wręcz zalecanym rozwiązaniem dla animowanych przejść ekranów w React Navigation. Działa bezkonfliktowo z react-native-screens
i gesture-handler
.
3. Jakie animacje mogę stworzyć z Reanimated?
Praktycznie każde – od prostych fade-inów i transformacji, po zaawansowane bottom sheets, interaktywne carousels, drag & drop, swipeable lists czy płynne reakcje na gesty i scroll. Reanimated daje pełną swobodę.
4. Czy Reanimated działa zarówno na Androidzie, jak i iOS?
Tak. Reanimated działa natywnie i w pełni wspiera obie platformy — iOS i Android. Co ważne, działa płynnie nawet na starszych urządzeniach i średniej klasy telefonach.


