React Native Reanimated - an introduction to smooth and efficient animations in mobile apps
Want to create smooth, responsive animations in React Native that really look and work like native animations? Learn about React Native Reanimated - a powerful animation library that works outside of JavaScript threads. In this step-by-step article, we explain how it works, when it's a good idea to use it, and how to start creating modern, powerful mobile interfaces using Reanimated.

- 1. Was ist React Native Reanimated?
- 2. When and why should you use React Native Reanimated?
- 3. Basic concepts and terms
- 3.1. useSharedValue
- 3.2. useAnimatedStyle
- 3.3. Worklets
- 3.4. Animators: withTiming, withSpring, withDelay
- 3.5. runOnUI i runOnJS
- 3.6. useDerivedValue
- 3.7. useAnimatedReaction
- 3.8. useAnimatedGestureHandler
- 3.9. interpolate i interpolateColor
- 4. How to install and configure React Native Reanimated?
- 5. We create the first animation – smooth appearance and zoom of the component
- 5.1. Preparing values for animation
- 6. Reanimated vs Animated – why switch to a modern approach?
- 6.1. Example – opacity animation in both approaches:
- 7. The most common mistakes and pitfalls
- 7.1. Missing plugin in babel.config.js
- 7.2. Incorrect components (e.g. View instead of Animated.View)
- 7.3. Using setState inside the worklet
- 7.4. Attempting to animate a style that does not support native drivers
- 7.5. Forgetting about value
- 8. Why is React Native Reanimated more than just “pretty” animations?
- 9. Recommended learning resources
- 10. FAQ – frequently asked questions
- 10.1. Can I use Reanimated with Expo?
- 10.2. Does Reanimated work with React Navigation?
- 10.3. What animations can I create with Reanimated?
- 10.4. Does Reanimated work on both Android and iOS?
Was ist React Native Reanimated?
React Native Reanimated is an advanced library for creating powerful native animations in applications built on React Native. It was developed and is being developed by Software Mansion – a Polish company specializing in creating tools for the React Native environment, which is also behind such projects as react-native-gesture-handler and react-native-screens.
When and why should you use React Native Reanimated?
React Native Reanimated works best when you want smooth, responsive animations that don’t fail even in more complex user interfaces. Unlike the standard Animated API , Reanimated runs on a native UI thread, which means that animations are not dependent on JavaScript performance.
With this:
- animations do not clip, even when the application is performing intensive background operations,
- We can seamlessly combine them with gestures (e.g., drag, shift, pull),
- provide a user experience similar to native applications,
- work well in components such as bottom sheets, carousels, swipeable lists, drag & drop and many others.
It’s worth reaching for Reanimated when:
- classic
Animatedbegins to choke or is difficult to expand, - you care about a modern, smooth UI (e.g., screen animations, transitions, modals),
- you create interfaces that are strongly dependent on gestures and touch.
It’s a tool designed for applications to “feel” native – regardless of the platform.
Basic concepts and terms
In order to effectively use React Native Reanimated, it is useful to understand some key concepts that differentiate this library from the standard approach in React Native:
1. useSharedValue
This is a special value type that lives outside the JavaScript thread and is shared with the native UI. We use it to store variables that will be animated (e.g. position, scale, transparency).
const opacity = useSharedValue(0);
2. useAnimatedStyle
A hook that allows you to assign animated values to a component style. It connects to shared value, to dynamically update the style without reloading the component.
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value,
}));
3. Worklets
Worklets are functions labeled "worklet", which are run outside the main JS thread – directly on a native engine (such as Hermes). This is the key to smooth animations that don’t depend on JavaScript performance.
runOnUI(() => {
'worklet';
sharedValue.value = withSpring(1);
})();
4. Animators: withTiming, withSpring, withDelay
Reanimated offers ready-made methods for animating values:
withTiming– linear animation in time (e.g., for transparency),withSpring– spring animation with physics (ideal for displacement),withDelay,withSequence,withRepeat– animation combinations for complex effects.
5. runOnUI i runOnJS
These functions allow communication between the native animation thread and JavaScript logic:
runOnUI()–runsa function on the UI side (e.g., at the start of an animation),runOnJS()– allows from the native context to call JS (e.g. callback after the animation is finished).
6. useDerivedValue
Creates a value that depends on other shared values, automatically updating when they change.
const derived = useDerivedValue(() => {
return sharedValue.value * 2;
});
7. useAnimatedReaction
It reacts to changes in shared values, allowing side effects to be performed in response to these changes.
useAnimatedReaction(
() => sharedValue.value,
(newValue, oldValue) => {
// response to a change in values
}
);
8. useAnimatedGestureHandler
It integrates gestures with animations, enabling smooth user interactions with the interface.
const gestureHandler = useAnimatedGestureHandler({
onStart: (event, context) => {
// gesture started
},
onActive: (event, context) => {
// active gesture
},
onEnd: (event, context) => {
// gesture ended
},
});
9. interpolate i interpolateColor
Functions for converting values from one range to another, often used to create smooth transitions.
const animatedStyle = useAnimatedStyle(() => {
return {
opacity: interpolate(sharedValue.value, [0, 1], [0.5, 1]),
};
});
How to install and configure React Native Reanimated?
It is very simple and will not cause you much trouble. You need to properly install the library and configure the project. Below you will find the steps needed to run Reanimated in a typical React Native application.
1. To install React Native Reanimated run in terminal:
npm install react-native-reanimated
If you use Expo, remember that Reanimated is already part of the SDK, but you need to make sure you have the right version.
2. Next, in the babel.config.js file, be sure to add the Reanimated plugin at the end of the plugin list:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin'], // <-- must be the last!
};
We create the first animation – smooth appearance and zoom of the component
Now that you know how to install the library, now we’ll create a component that appears smoothly on entry and zooms in slightly. Such animations are very often used in real applications – for example, to present product cards, welcome banners, notifications or onboarding screens.
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',
},
});
What’s going on here?
Preparing values for animation
const opacity = useSharedValue(0);
const scale = useSharedValue(0.8);
What does this do?
We create so-called “shared values”, which are special variables that will change during animation – but without affecting the main React thread. opacity controls transparency, and scale is responsible for size.
We then run the animation when the component appears:
useEffect(() => {
opacity.value = withTiming(1, { duration: 800 });
scale.value = withTiming(1, { duration: 800 });
}, []);
Why is this?
We use withTiming, to smoothly change the values over time. Theopacity increases from 0 to 1 (the component becomes visible) and the scale from 0.8 to 1 (a slight ‘zoom’ effect).
We create an animated style:
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{ scale: scale.value }],
}));
This style will dynamically update along with our shared values. It works like “magic” – no setState, no flashing, no slowing down the application.
The use of an animated component:
<Animated.View style={[styles.card, animatedStyle]}>
<Text style={styles.text}>Welcom to Reanimated 🎉</Text>
</Animated.View>
We use Animated.View, because only it can understand animated styles. Text itself doesn’t animate – only the container it’s in.
Reanimated vs Animated – why switch to a modern approach?
From the outset, React Native has offered the Animated library, which allows you to create animations in applications. However, with growing user expectations and the need for better performance, many teams began to look for a more flexible solution. This led to the creation of React Native Reanimated, a tool that breaks with the limitations of the old approach.
1. PerformanceAnimatedruns on a JavaScript thread, which means that every animation goes through the JS-Native bridge. In practice, this leads to delays, especially if the application is heavily loaded. Reanimated, on the other hand, executes animations directly on the native UI thread, resulting in smoothness comparable to mobile applications written in Swift or Kotlin.
2. API and coding styleAnimated is based on an imperative approach — we need to create an animation variable (new Animated.Value()), initialize it, and then “manually” start the animation using .start(). In Reanimated, we work in a declarative way: we use hooks such as useSharedValue or useAnimatedStyle, which makes the code more readable and logical, especially in large projects.
3. Component re-renderingAnimated often requires additional tricks to animate components without constantly reloading them. Reanimated does not need re-renders — all values live outside React and are updated in the background, which has a positive impact on performance and stability.
4. Gesture support
With Animated, animating in response to gestures (e.g., swiping) can be difficult and counterintuitive. With Reanimated, thanks to tight integration with react-native-gesture-handler, gesture support is natural and very precise. You can create complex interactions with the fluidity of a native app.
5. Flexibility and capabilities
Reanimated gives you access to advanced tools such as withSpring, withSequence, withDelay, interpolate, useDerivedValue, and runOnJS. No other animation API for React Native offers this kind of flexibility. In comparison, Animated feels quite rigid and requires more work for complex use cases.
6. Support and developmentAnimatedis an older API that has been around for a long time in React Native, but is currently being developed very slowly. Reanimated is an active, modern project developed by Software Mansion, supported by a large community, and used in many top mobile apps.
Example – opacity animation in both approaches:
Animated:
Animated.timing(animatedValue, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}).start();
You have to separately create a reference(new Animated.Value(0)), take care of start(), and worry about useNativeDriver.
Reanimated:
opacity.value = withTiming(1, { duration: 500 });
The most common mistakes and pitfalls
Reanimated is a powerful library, but like any tool – it has its nuances. Especially at the beginning, it’s easy to make some common mistakes that can lead to frustration and non-obvious errors in the operation of the application. Here’s a list of the most common problems and their causes:
1. Missing plugin in babel.config.js
The most common classic – forgetting to add "react-native-reanimated/plugin" in the babel.config.js file . The plugin must be last in the list of plugins – otherwise the code from the worklet will not be processed correctly.
plugins: ['react-native-reanimated/plugin'] // <-- the last!
2. Incorrect components (e.g. View instead of Animated.View)
If you try to useAnimatedStyle on a regular View, nothing will happen – the animated style must be assigned to a component from the Animated space .
Correct:
<Animated.View style={animatedStyle} />
Incorrect:
<View style={animatedStyle} /> // Won't work!
3. Using setState inside the worklet
Worklets run outside React, so you can’t use functions like setState() or console.log() inside them without using runOnJS. If you need to run something in the JS world from within a worklet, use:
runOnJS(setState)(newValue);
4. Attempting to animate a style that does not support native drivers
Not all styles can be animated in Reanimated (e.g. zIndex, flexGrow, fontWeight — in some versions). It is always a good idea to test the animation step by step and only use supported properties.
5. Forgetting about value
In the case of sharedValue, you must refer to .value — this is the most commonly overlooked detail by people learning Reanimated.
Correct:
opacity.value = withTiming(1); // ✅
Why is React Native Reanimated more than just “pretty” animations?
At first glance, React Native Reanimated may seem like just a library for beautifying interfaces. However, its role in a mobile application goes far beyond aesthetics. In modern mobile app development, animations are not just a visual addition — they serve informational, organizational, and emotional functions. Reanimated allows you to implement them in a way that is both technically efficient and design-conscious.
Well-designed animations make it easier to understand the context of an app: they show the relationships between elements, inform about changes in status, guide the user through the next steps, and give rhythm to interactions. Instead of surprising transitions or sudden changes in layout, the user gets a smooth, consistent flow that enhances the sense of control and intuitiveness. Reanimated allows for very precise reproduction of such microinteractions — without lag, with full control over gestures and animations.
From a technical perspective, Reanimated is also an architectural tool. Moving the animation logic to a native thread significantly reduces the load on the main JavaScript thread, which is extremely important for complex screens, asynchronous data, gestures, and scrolling. In applications that need to run smoothly on mid-range devices, this separation of logic is a prerequisite.
Reanimated also allows you to write your interface in a declarative, consistent, and easy-to-test way. Creating animations no longer requires separate component state management or workarounds. Component behavior logic can be written as clean, deterministic functions based on sharedValue, useDerivedValue, or interpolate. This makes the code simpler, more readable, and easier to maintain.
That’s why Reanimated should not be treated as just a library of “pretty effects.” It is a full-fledged engineering and UX tool that allows you to design interfaces more consciously — with an emphasis on usability, performance, and predictability. In the modern world of mobile apps, this is not just an advantage. It’s the standard.
Recommended learning resources
If you want to better understand the potential of Reanimated and deepen your knowledge, it’s worth checking out a few proven sources that will help you step by step, such as: https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/, https://github.com/software-mansion/react-native-reanimated
FAQ – frequently asked questions
1. Can I use Reanimated with Expo?
Yes, Reanimated works with Expo, but full support (especially for gestures and some native features) is available from SDK 46 onwards. Make sure you have the latest version of Expo and the Babel plugin configured correctly.
2. Does Reanimated work with React Navigation?
Yes, and very well. Reanimated is even recommended for animated screen transitions in React Navigation. It works seamlessly with react-native-screens and gesture-handler.
3. What animations can I create with Reanimated?
Practically any—from simple fade-ins and transformations to advanced bottom sheets, interactive carousels, drag & drop, swipeable lists, and smooth reactions to gestures and scrolling. Reanimated gives you complete freedom.
4. Does Reanimated work on both Android and iOS?
Yes. Reanimated works natively and fully supports both platforms — iOS and Android. Importantly, it runs smoothly even on older devices and mid-range phones.


