React Native Animations: Part 2

image of colorful code on mac laptop screen

When we build apps for our clients, beautiful designs and interactions are important. But equally important is performance. Without a fast frame rate our fancy animations will stutter to a halt. Without responsive taps and swipes our users will grow impatient and leave. Fortunately the creators of React Native care about performance too. They’ve given us a way to optimize animations and keep them blocking our JavaScript code. Here we’ll look at how to use “Native” animations, their benefits, and their limitations.

How to use native animations

Changing an animation driver (like Animated.Timing or Animated.Spring) to use native animations is as easy as adding the property useNativeDriver: true. The same goes for an Animated.Event:

You should use native animations whenever possible.

What’s the difference between native and non-native animations?

In React Native apps there are 2 threads: a UI thread and a JavaScript thread. The JavaScript thread handles EVERYTHING JS-related. All your business logic, API calls, React component diffs and updates. The UI thread is the iOS or Android side of things. It renders the underlying views, and handles any native modules you’re using. Even if your JavaScript is working hard and blocking the thread, you can still scroll a ScrollView fluidly because it’s running on the native side.

Usually animation runs mostly on the JavaScript thread. But we can push it over to the UI thread, freeing up the JS thread to do more work. In our last post we looked at how Animations work: changes to Animated Values trickle down to change other values, which trickle down to change props, which get passed across the JS–native barrier. In the UI thread, iOS or Android updates the UIView or android.View. JavaScript is already doing a lot of work, and we’re adding animation handling on top of it. This is likely to result in stuttering and jank. Using a Native Driver we can let the native code take care of everything. JavaScript gets more overhead to do other computations, which means fewer dropped frames and smooth animations.

Here’s how it works: When the animation starts, the Animation graph (all the connected Animation Values, Transforms and Props) is serialized and sent across the bridge to the native side. The native side iterates through the graph and calculates all the properties, setting them directly on the views. Some types of animations can even be precalculated at start time for more optimization. There’s no reliance on the JS thread—the UI thread does all the work. Animations run smoothly even when complicated component renders block the JS thread.

Why would we use anything but native animations?

Most of the native animation features were only added in late 2016 or early 2017. They may not be supported on older version of React Native. And even now, there are limitations.

You can only animate a few layout properties using native animations. If you try to use an unsupported property, you’ll get a message like “Style property ‘height’ is not supported by native animated module”.

Here’s the list as of React Native 0.51.0:

Noticeably lacking are width, height, elevation, and color. You’ll want to rely on the transform properties wherever you can. If you do need to fall back to non-native animations, keep it limited. Avoid non-native animations in global app components, like navigation or navbars/headers.

You can’t mix native and non-native animation nodes. If you kick off your animation using the native driver, all connected transforms and animated values will need to use the native driver as well. And only these props can be set with the resulting value. And no easing: you’re stuck using linear animations.

Further reading

To find our more about native animations, checkout the React Native Blog’s official announcement.

We’re hoping support for native animations continues to improve. There is talk in the GithHub issues about moving all animation work over to the UI thread, or optimizing in other ways. By knowing more about how all this works under the hood, this stuff get easier to build and debug. React Native’s animation framework will let you create fancy, performant animations without writing Swift or Java code.

Do you have a project in mind? We’d love to work with you. If you’d like an opportunity to work on projects with us, check out our Careers page. We’re hiring!

One response to “React Native Animations: Part 2”

  1. Any idea how can we animate fontSize with nativeDriver

Leave a Comment