DEV Community

Cover image for Optimizing animations for 60 FPS with React Native Reanimated
Malik Chohra
Malik Chohra

Posted on

Optimizing animations for 60 FPS with React Native Reanimated

Before we start, a word:

I started working on an AI native Boilerplate for Mobile Development. A solution that has a scalable and clean architecture, with the best approaches to have a great app performance. Adding more AI context and rules, to make the AI hallucinate less, and keep the clean code. You can use it either with Cursor, Antigravity, Claude Code,… and it gives the amazing results as expected. Also, it has most important features that help you launch your app fast
I m now in the Beta version, where i need people to test it, and gather feedback, you will get access to the code base for free, and i m looking for feedbacks.

Check it here: https://aimobilelauncher.com/

Also, I m working on a newsletter for Tech and non tech people, on how to use AI tools for App development: https://aimeetcode.substack.com/. Subscribe here: https://aimeetcode.substack.com/
If you need custom solution, or a mobile development, contact us in :https://casainnov.com/

Introduction

Smooth animations aren't a "nice-to-have." When users say "this app feels slow," they almost always mean animations are dropping frames - even if they'd never describe it that way.
After shipping features on apps with millions of active users, I've learned that animation performance is one of the first things that breaks at scale and one of the hardest to debug if you haven't seen the failure modes before. Here's what actually holds up in production.

Speaking of scale: in Mobile apps, I mean by scale is a bigger team, a lot of users who each person have a different devices, operating system, slow and old devices, or different sizes. In this part, you need to architect your app way better before

TL;DR

60 FPS means keeping animations off the JS thread
Use shared values, not React state
Animate transform + opacity; avoid layout properties
Batch animations and keep logic simple
Test on real devices, not simulators

Why it matters

Dropped frames make an app feel slow. Janky gestures make it feel cheap. And inconsistent motion is hard to explain to a product manager but immediately obvious to users. Beyond UX, smoother animations also mean better battery life, better behavior on low-end devices, and less competition with your business logic.
The one rule that matters most

If your animation depends on the JS thread, you've already lost.
Reanimated runs animations on the UI thread, independent from JS. Everything else in this article is just ways to not break that.

1. Animate only what the native driver supports

Safe: transform, opacity. Slow: width, height, backgroundColor, anything layout-driven.
`
// Good
const style = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{ translateY: y.value }, { scale: scale.value }],
}));

// Bad
const style = useAnimatedStyle(() => ({
width: width.value,
height: height.value,
}));`

If you feel like you need to animate the layout, stop and rethink the design. The animation is probably covering for a structural problem.

2. One shared value, not five

I still see this in senior-level code:

// Too many values
const opacity = useSharedValue(0);
const scale = useSharedValue(0);
const translateY = useSharedValue(0);
Collapse them:
const progress = useSharedValue(0);
const style = useAnimatedStyle(() => ({
opacity: progress.value,
transform: [
{ scale: progress.value },
{ translateY: (1 - progress.value) * 20 },
],
}));

One value, fewer calculations, smoother frames. The math is trivial on the UI thread.

3. Batch your animations

Starting animations at different times means the thread is doing more work than it needs to. A single withTiming can drive opacity, scale, and translation at once:

useEffect(() => {
progress.value = withTiming(1, { duration: 300 });
}, []);

Obvious in hindsight, but easy to miss when you're wiring up components quickly.

4. Springs for gestures

Timing functions work fine for entrances and exits. For gestures, springs are better - they feel more physical, and they put less pressure on the frame budget:

translateX.value = withSpring(0, {
damping: 15,
stiffness: 150,
});

This matters most for drag, swipe, and scroll interactions, where any stiffness or lag is immediately noticeable.

5. Keep gesture handlers dumb

No conditionals. No calculations. No JS calls inside gesture handlers.

onActive: (event) => {
x.value = event.translationX;
y.value = event.translationY;
}

The UI thread moves pixel. Anything else belongs else where.

6. Clean up animations

Animations that outlive their components create memory pressure. Easy to overlook, adds up on apps with deep navigation:

useEffect(() => {
return () => {
progress.value = 0;
};
}, []);

7. How to test

Simulators will lie to you. A simulator doesn't have thermal throttling, doesn't run on 3GB of RAM, and doesn't have fifteen background apps fighting for CPU. Test on low-end Android, older iPhones, and devices that have been warm for a while.
If it holds up there, you're fine.

Always go with an old device,

What I actually see in code reviews

Animating every component entry - motion should mean something; overuse kills that
Animations tied to React state - state updates and animation updates are not the same thing
Durations over 500ms - they feel slow and block frames; tighten them
Elaborate easing curves - usually not worth it; keep it consistent

Before you ship

Ask yourself: Is this running on the UI thread? Can one shared value drive it? Did I test it on real hardware? If yes across the board, you're done.

FAQ

Does Reanimated always guarantee 60 FPS?
 No. It gives you the right architecture. You still have to use it correctly.

Should I use Reanimated for every animation?
 Not necessarily. Simple layout animations are fine with LayoutAnimation. Reanimated earns its complexity with gestures and anything UI-thread-sensitive.

Are springs always better than timing?
 For interactions, yes. For entrances and exits, timing is usually fine and easier to control.

Is performance worse with Expo?
 No. Expo and Reanimated together are production-proven

Example from the AI Mobile Launcher

Top comments (0)