What the React Native docs forgot to tell you about animations

Karen de Graaf
Mar 12, 2018 · 5 min read
Image for post
Image for post

React Native is great. It’s pretty awesome to be able to build a native app with only JavaScript knowledge. One of the things I like most is making the animations, it can add so much to the experience of an app. Unfortunately React Native’s documentation about animations is not so great. Some things are explained rather vaguely and other things are plain missing. That’s why I wanted to give you a quick overview of the things I think need a bit of extra explanation. There’s still more out there, but these are the things you’ll probably need most.

One last thing to note before I begin, I write this as an addition to the React Native documentation. You should check that first if you haven’t already. Here I’ll try not to repeat too much from the original docs.


The Animated library has 3 functions to animate things on screen, Animated.timing, Animated.spring and Animated.decay. How to use them is pretty clear from the documentation, but when to use which function can be confusing.

Animated.timing gives you the most control. You define the duration and you set the easing. Especially if you’ve got a specific easing from the motion design, this could be your easiest option. However, if you don’t have a predefined easing, it can be hard to give the animation the right feel. Then Animated.spring is your better option. This function provides a spring physics model, it’s based on movements from the real world.

There are 3 option combinations to modify the spring motion: friction/tension, bounciness/speed and damping/stiffness and mass. The last one gives you the most control, the mass of the others is automatically 1. All three have different sensitivities, so it’s good to play around with them a bit to see which one gives you the best results. Here I’ll explain what changing the value of one of the options would do to your animation.

The resistance that one surface or object encounters when moving over another. A lower friction value gives more overshoot (the amount it moves beyond the toValue) and bounces more often.

Tension is like a rope pulling on a box, the force that is transmitted through the rope is tension. This controls the speed on an animation, a higher tension gives a faster-moving animation.

Image for post
Image for post
Example of a high bounciness

Does what it says, an increased bounciness will increase the overshoot and the number of bounces. An easy way to create a crazy bouncing object.

The speed of the animating object, has no influence on the overshoot or the number of bounces.

Animations with damping, stiffness and mass are based on a Damped Harmonic Oscillator. Each bounce is described as on oscillation.

Reducing the damping value reduces the energy loss with each oscillation and there will be more overshoot. Increasing the value increases the energy loss with each oscillation, there will be fewer and smaller oscillations and the duration will be shorter.

A higher stiffness increases the overshoot and the speed of the motion.

Adapting the mass value will change the momentum of the animation. An increased mass, a heavier object, has a slower start and a more rounded bounce. A higher mass also makes the duration of the animation longer.

The last animation function is Animated.decay() and has some specific use cases. It requires you to set an initial velocity. Based on that and a deceleration value, it calculates what the end value is and how long the animation should take. For example, if you use it with a translate, a high velocity will move the animating element off screen and a lower velocity only moves it a few pixels. It gives you little control over the results, but it can work for a user gesture initiated animation. You could, for example, use it for a momentum based slider.

One important thing to add in case you missed it in the React Native docs, try to add useNativeDriver: true as often as possible. It will greatly improve the smoothness of your animations. As the docs say:

“By using the native driver, we send everything about the animation to native before starting the animation, allowing native code to perform the animation on the UI thread without having to go through the bridge on every frame. Once the animation has started, the JS thread can be blocked without affecting the animation.”


React native provides you with a list of predefined easing functions, but not much guidance about what to do with them. The easing functions can be wrapped by Easing.in, Easing.out or Easing.inOut, but you can’t use these on their own. Ease-in is the default mode, so you don’t necessarily need to wrap your functions with Easing.in.

easing: Easing.in(Easing.quad)
// is the same as {
easing: Easing.quad

Next to the predefined functions, you can make your own easing function. It is pretty simple if you look at the source code. For example, a cubic easing function can be added as the following, where t is the elapsed time.

easing: (t) => t * t * t

Or you can use the Cubic bezier like you would in css.

easing: Easing.bezier(0.645, 0.045, 0.355, 1)

Two of their functions remain a mystery to me though, the step0 and step1 functions. The first one returns 1 for any positive value of n and the second returns 1 if n is greater than or equal to 1. I couldn’t figure out any use case for that, so if you have any idea, I’d really like to hear about it in the comments.

The hidden helper functions


When a variable has been set with new Animated.Value(), it has the setValue function exposed to it. It gives you control over the value without having to animate it. One of the cases this can be useful for is to set an animating variable to its original value when animating it multiple times.

this.animatedValue = new Animated.Value(0);
this.animatedValue = new Animated.ValueXY({x: 15, y: 30});
this.animatedValue.setValue({x: 0, y: 0});


This method with transform your {x: 10, y: 200} value to a directly usable transform.

this.animatedValue  = new Animated.ValueXY({x: 10, y: 200});<Animated.Value style={{
transform: this.animatedValue.getTranslateTransform()
}} />
// is short for <Animated.View style={{
transform: [
{translateX: this.animatedValue.x},
{translateY: this.animatedValue.y}
}} />


Stops any running animation. It has a callback with the final value after the animation has stopped.

this.animatedValue.stopAnimation((finalValue) => {
console.log('finalValue: '+ finalValue)


Stops any running animation and sets the value back to its original value. Other than that it works the same as stopAnimation.


I hope this makes working with React Native animations a little more clear. Maybe even some more fun. In the end just experimenting with different functions and options will give you the best results. It might take some time to get used to the Animated api, but you will get the hang of it.


We make the online world beautiful, easy and insightful

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store