Animations in React Native. How to achieve great performance and tips — 1x04
This story is part of a series where I am sharing my experiences on React Native: how I approached and worked with RN Components, APIs, external packages and all sorts of issues. I hope that this series of posts will prove useful to the React Native community and provide helpful insights. For app development enquiries check us out or contact me here.
Why are animations important?
Animations are important in order to create an optimal user experience, especially in the mobile world. App users have been exposed to a lot of them already, and have become familiar with their usability and beauty. And since they have hands-on experience with them, they expect them as a given in every single app they download. As per the React Native animations documentation:
Objects in motion have momentum.
Animations allow you to convey physically believable motion in your interface.

Animation systems in React Native
React Native provides two complementary animation systems: Animated and LayoutAnimation. These are 2 different APIs with a different usability and purpose.
My personal feeling is that Animated is more widely used from developers, probably because it provides more control — and it also comes with better documentation.
In this article I assume that you are familiar with Animated API and I will blog on how to achieve the best performance out of it, alongside some other practical tips.
Animated API tips: Performance and more
In order to create an animation you can find very good documentation and “how to start” examples in React Native animations documentation.
How to achieve great performance
To achieve great performance you always need to make use of the configuration prop useNativeDriver
(with value set to true
). For example, in order to animate the rotation of an image our timing function would look like that:
Animated.timing(
this.state.spinValue,
{
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true
}
).start();
This config prop is very very important because that way, RN sends the animation to be executed at the native realm directly passing through the bridge only once, thus achieving the best possible performance. If you are not familiar with the JavaScript/native realms and their bridge, you can get more insights in this post by @TalKol.
Now, according to RN documentation useNativeDriver
prop cannot be used for all animation types:
Not everything you can do with Animated is currently supported in Native Animated. The main limitation is that you can only animate non-layout properties, things like transform and opacity will work but flexbox and position properties won’t.
There is a way though to overcome this, if you are composing animations. For instance let’s take an example from the Math Warriors Android app where we change the size of our logo image when the user clicks the start game button.

What we do at this point is that we change the width and height of the logo simultaneously and these properties do not support use of the animated driver property. Their parallel execution though does support it as shown below:
Animated.parallel(
[
Animated.timing(
this.state.rankImageWidth,
{
toValue: 110
}
),
Animated.timing(
this.state.rankImageHeight,
{
toValue: 110
}
)
],
{
useNativeDriver: true
}
).start();
How to perform animations in loops
RN does not support loop animations out of the box, so we had to find a way. A 2nd example from Math Warriors game, which is actually the extension of our previous example, is the following: as soon as the user presses the start game button, the logo increases its size and also starts moving up and down in a loop and until the app matches the player with an opponent.

We performed this by creating a JavaScript interval id. The catch here is that in order to avoid app glitches and waiting time, you need to execute the actual animation twice: the 1st one and all the others that will follow inside a loop (JavaScript interval).
// Animation function that moves an element over y axis over time
const upAndDown = (yPositionPropName, duration, yHighPosition, yLowPosition) => {
Animated.sequence([
Animated.timing(yPositionPropName, {
duration: duration || 1000,
toValue: yHighPosition
}),
Animated.timing(yPositionPropName, {
duration: duration || 1000,
toValue: yLowPosition
})
]).start();
};
// Call and use the function above
// Start up & down animation for the first time before the loop takes over
upAndDown(
this.state.rankImageTopPosition,
this.rankImageMoveDuration,
this.rankImageHighposition,
this.rankImageLowposition
);// Loop rank image up & down movement. Total interval time
// is (animation duration x 2) time for the whole up & down move
this.rankAnimationIntervalId = setInterval(() => {
upAndDown(
this.state.rankImageTopPosition,
this.rankImageMoveDuration,
this.rankImageHighposition,
this.rankImageLowposition
);
}, this.rankImageMoveDuration * 2);// Clear the interval id after we match our player with an opponent
clearInterval(this.rankAnimationIntervalId);
How to use animatable components with styled components
For the users of styled components you can convert any of the 4 animatable components (View
, Text
, Image
, ScrollView)
to a styled component like that:
const AnimatedImage = styled(Animated.Image)`
.
.
.
`;
Validate animation’s real performance
In order to understand how your animation will behave you need to test it on a real device. Emulators cannot provide this kind of feedback. On the contrary, your animation may run flawlessly in an emulator environment and be sticky on a real device. Only the real device test can reveal if the animation shows at 60 FPS or less, which is when we experience slow breaking animations.
What do you think?
What do you think about these animations’ tips? How do you make your animations work for you? Offer your perspective and ideas in the comments section below.
Do you have a specific subject that you would like me to cover? If I have worked with it, I will be more than happy to share my perspective.
If you enjoyed this article, feel free to hit that clap button 👏 to help others find it.
About me
Hi there, I’m Tasos; a software engineer that currently works a lot with React Native. I’m the Founder of Coded Lines where among other things we create user engaging mobile apps that help companies drive growth to their brands. Check us out or contact me here. Thanks for stopping by :)