Do you find yourself struggling with delayed and laggy animations in your apps? You’re not alone. The standard Animated API we all know and love is great, but it’s not up to the job of fast, buttery-smooth 60FPS animations needed in modern apps.
This is where React Native Reanimated comes in. Reanimated is an invaluable innovation that lets developers make high performance animations in React Native - all without learning a whole new framework. With shared values and Reanimated worklets, Reanimated unlocks endless new opportunities to connect with and retain users.
This React Native Reanimated guide is your one-stop shop for learning the ropes. Our experts will give you a simple useSharedValue tutorial, go over Reanimated worklets, and compare React Native Reanimated 3 vs 4 to help you build the best animations possible.
The Reanimated Philosophy
We’ve all had that experience of using an app for the first time and being disappointed it feels somehow “cheap.” More often than not, this is down to “jank” - stuttering, lagging, freezing.
Jank arises from a straightforward JS-UI problem. With older animation models like the Animated API, there are two main elements:
- The JS thread - the thread that makes decisions and handles the business logic.
- The UI thread - the thread that draws the screen and moves things around.
This system means the UI has to “ask permission” and wait for the JS thread to react - a JS thread that’s often busy doing something else. Although these delays are usually only milliseconds, your brain definitely notices them!
Reanimated solves this by delegating decision-making power to the UI thread itself. Instead of relying on the JS thread for instructions, it simply knows the rules and follows them by itself.
This means:
- Animations keep running and stay smooth.
- Frames are never skipped.
- Your finger and the screen move together.
- The app feels native and solid.
That also means developers have an easier job; they only have to define animation rules once.
Core Concepts Breakdown: useSharedValue & Reanimated worklets
So, how does Native React Reanimated actually work? It’s not magic. It’s a careful combination of coding innovations that free up the UI thread to think for itself. The two main ideas behind Reanimated are useSharedValue and Reanimated worklets.
Let’s break these down and see what they actually mean:
useSharedValue
One of the biggest problems with traditional Animation API systems is the gap between the JS thread and the UI thread. The key thing is that these two threads can’t normally see each other. The UI thread has to wait for the JS thread to respond.
Shared values solve this problem. These are small pieces of information that both the JS thread and UI thread can read and update. Think of it like a shared whiteboard in an office. This information might contain:
- A position (x = 120)
- A scale (1.0 → 0.8)
- A progress value (0 → 1)
useSharedValue - the tool you use to create shared values in Reanimated - plugs the gap between the threads and allows for instant communication.
Reanimated worklets
Here’s the problem: JavaScript runs only on the JS thread and the UI thread can’t understand JS logic. This is why we get the gap - and jank.
But this is where Reanimated worklets save the day. These are small pieces of JavaScript that get copied and executed directly on the UI thread. This essentially means the UI thread can now think for itself and provide full animation speed using JavaScript rules.
worklets decide things like:
- “If the finger moves left, move the card left”
- “If the swipe is fast, keep moving”
- “If progress > 0.5, snap open”
However, you should note that worklets are limited. You can’t rely on them to call random functions as they can’t access the whole app - only what they’re designed to do. This is what makes them super fast.
Building High-Performance Animations With React Native Reanimated: Getting Started
Follow a few simple steps to get React Native Reanimated up and running:
Installation & Babel Configuration
There are two main parts to React Native Reanimated installation: the JavaScript package and native setup.
Let’s go through both:
Step 1: Install the Package
NPM:
npm install react-native-reanimatedYARN:
yarn add react-native-reanimatedStep 2: Install Native Dependencies
iOS:
cd ios
pod installAndroid:
No manual steps needed as long as you’re using React Native 0.64+.
Step 3: Rebuild the App
You have to rebuild as Reanimated includes native code. Do this with:
npx react-native run-iosOr;
npx react-native run-androidStep 4: Babel Configuration
Because Reanimated uses worklets you need Babel to detect them and transform them correctly.
You first need to open your babel.config.js and add the Reanimated plugin last:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'react-native-reanimated/plugin',
],
};We recommend that you restart Metro and clear your cache after this, like so:
npx react-native start --reset-cacheMoving to the New Architecture (Fabric)
You don’t technically have to move to Fabric to use Reanimated, but you’ll need it to run Reanimated 4 (the latest version). It’s the future, so we recommend taking the leap.
Fabric is much smoother and more efficient than older architecture. UI updates are much faster and thread communication is cheaper.
Here’s how to enable it:
Step 1: Enable Fabric
This process differs for iOS and Android. Here are some simple instructions for both:
iOS (in your ios/Podfile):
ENV['RCT_NEW_ARCH_ENABLED'] = '1'Then:
cd ios
pod installAndroid (in android/gradle.properties):
newArchEnabled=trueThen:
npx react-native run-androidBuilding Your First Animation
Let’s assume you have Reanimated up and running and Babel is configured. You’re ready to get started on your animation.
Below is a practical example you can use to get a feel for the process. We’re going to show you how to create a box that smoothly moves to the right using a spring animation:
Step 1: Import What You Need
We need:
- useSharedValue to store the animation state.
- useAnimatedStyle to turn that state into visuals.
- withSpring to define the movement behavior.
Import these like so:
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';Step 2: Create a Shared Value
Use:
const translateX = useSharedValue(0);Step 3: Create an Animated Style
We need to describe how data from the shared value turns into visual movement. Do this with:
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [{ translateX: translateX.value }],
};
});Step 4: Trigger the Animation
This is where withSpring comes in. We’re going to tell Reanimated how to reach the new target value:
const moveBox = () => {
translateX.value = withSpring(150);
};Step 5: Apply the Animated Style
Here’s where we attach our rule to the specific view. Use:
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Animated.View style={[styles.box, animatedStyle]} />
<Button title="Move" onPress={moveBox} />
</View>
);Using Interactive Gestures
Want to go a step further? You’re ready to start exploring interactive gestures. These are touch-driven actions like dragging or swiping - not just clicks. You can actually track where the finger is. This opens up a world of possibilities in Reanimated.
However, the bottom line is React Native’s default touch handling is not precise enough for these kinds of complex gestures. We need a “react-native-gesture-handler”.
react-native-gesture-handler integrates with Reanimated and lets gestures - pans, long presses, pinches, rotations, swipes - drive animations directly via shared values and worklets.
Let’s see react-native-gesture-handler in action with two examples:
1. Bottom Sheet Example
We need:
- translateY - shared value for vertical position.
- translateY.value - pan gesture update.
- useAnimatedStyle - moves the sheet.
- withSpring - snaps sheet to “open” or “closed” when released.
Here’s the flow:
Finger drags → PanGestureHandler → translateY.value updates → Animated.View moves2. Carousel Example
We need:
- translateX - shared value for horizontal position.
- translateX.value - pan gesture update.
- useAnimatedStyle - moves cards left or right.
- withSpring or withTiming - snaps to the nearest card when released.
Flow:
Swipe → translateX.value changes → card shifts → snap to nearest cardReact Native Reanimated 3 vs. 4: What’s New?
Reanimated 4 is the latest version at just a year old. Developers can still run Reanimated 3, of course, but we definitely recommend jumping to 4 - there are plenty of significant changes that make it the go-to choice for animations.
Here are just a few of the biggest updates between React Native Reanimated 3 vs. 4:
- Architecture - Reanimated 3 supports both the New Architecture (Fabric) and the Old React Native architecture (Paper). Reanimated 4, however, only supports Fabric.
- Worklets and core dependencies - Reanimated 3 has worklets built directly into the library, which means it all works straight out of the box. Reanimated 4 has separated worklets into a new package (react-native-worklets). The main advantage here is that other libraries can now also use the worklet tech, not just Reanimated.
- CSS‑style animations and transitions - Reanimated 4 gives us a whole new - and much smoother - approach to animations and transitions: familiar CSS‑like systems that make animations much easier to read.
- Performance - Reanimated 3 is still a reliable tool, no doubt about it. However, 4 has been further optimized for Fabric and concurrent rendering, making animation performance even smoother on the New Architecture.
Performance Best Practices
Reanimated is an ultra-reliable companion for developers. That said, there are of course plenty of small ways to accidentally harm performance, just like with any animation library.
Here are some key things to keep in mind:
- Keep animations on the UI thread - the JS thread is often busy elsewhere handling updates and this often leads to delays. Make sure you use shared values and worklets to run animation logic on the UI thread itself and cut out the middle man.
- Don’t overuse useAnimatedStyle logic - worklets are fast, but the heavier the computation, the slower the performance - especially at 60FPS. We recommend you keep all worklet functions inside useAnimatedStyle small and lightweight. This will keep things smooth.
- Avoid unnecessary re-renders of React components - when a view hierarchy re-renders in React every frame, it harms performance. Instead, only animate Animated.View components and avoid regular React views that re-render frequently.
- Limit worklet calls - always remember that anything that blocks the UI thread delays the frame. So, you should only run code inside worklets that needs to run per frame. Forget about fetching data from JS or reading large objects inside the worklet.
- Use gesture-handler efficiently - JS events (onPanResponderMove) to update animated values is slow and causes delays. It’s much better to combine react-native-gesture-handler with Reanimated shared values for immediate responsiveness.
- Test on real devices - often forgotten: always test animations on a physical device, not just a simulator or emulator! Simulators may hide frame drops or exaggerate performance.
This React Native Reanimated guide is designed to give you an overview of the library and teach you how to get started with shared values and Reanimated worklets. With this training, you’ll be able to integrate smoother, more satisfying animations and transitions into your app at a fraction of the speed and cost. For more info, feel free to contact the Tapptitude team today to discuss your app development needs!
FAQs
Is Reanimated compatible with Hermes?
Yes! Reanimated actually works very well with Hermes on Android and iOS. In fact, Hermes combined with Reanimated 4 gives you maximum performance.
How do I debug Reanimated worklets?
Because worklets run on the UI thread, normal console.log behaves differently. This has implications for debugging. You may need to use console.log inside worklets, or you might need to try runOnJS() or even enable a Reanimated debug overlay to speed things up.
How do I migrate from Reanimated 3 to 4?
You’ll first need to update dependencies with “npm install react-native-reanimated@latest react-native-worklets” and then Babel (replace “react-native-reanimated/plugin” with “plugins: ['react-native-worklets/plugin']). You should then check removed / renamed APIs and rebuild the native code.
Tapptitude
Tapptitude is a mobile app development company specialized in providing high-quality mobile app development services, and a top-rated app company on Clutch.