4 ways to add animations quickly to your React-Native projects

Felipe Morales
Nursoft
Published in
12 min readApr 29, 2019

Animations are a key feature for most modern mobile applications, not only because they are beautiful and add a modern feel to them, but also because they can communicate important information, call the user’s attention and enhance the flow that the user experiences.

Nowadays, most users have very high expectations when it comes to the feeling and flow of the applications they use. This makes it very difficult for an application that lacks any kind of animations to compete in the market, unless it is for a specific and unique task.

Adding animations is important, but it is also a very expensive process in terms of the amount of effort that the developers have to invest in order to observe results. Having efficient methods to implement the animations is very important to allow our engineers to focus on more challenging tasks such as image processing, face recognition algorithms and overall optimisation of the final product.

Why React-Native?

React-Native is one of the most popular frameworks used to deliver applications for multiple platforms without having to write code in different languages and eco-systems (for the most part). It allows for rapid project development and deployment, which results in reduced overall development time.

Regardless of how awesome React-Native is, we will always prefer to implement our animations natively as it gives us a huge advantage when it comes to both performance and flexibility. Since this requires additional knowledge of the Android and iOS ecosystem that not everyone using react-native may have (and should not really have to have), we will only focus on solutions that only require the use of react-native and its available libraries.

Quick introduction to animations

Animations and their intention can widely vary depending on the use case and the restrictions of the requirements where they are being implemented. There are multiple categorisations that can be used to classify each type of animation depending on its goal, how it behaves and how it triggers. For this post, I will use a categorisation that was introduced on Rachel Nabor’s “Animation at Work” (Very recommended read!):

  • Transition animations: Consist of all animations that take the user from one place or view to another. This normally implies that the animation will cause the current user’s goal to change or be significantly modified. Transitions are the most important kind of animation that an application can have as they effectively let the user know that the task has changed. They are also normally the most expensive to implement, considering both the time it takes to code them and all the variables that have to be tracked.
  • Supplement animations: All animations that modify the information being displayed in the view are of the supplement type. These animations are normally used to let the user know that information has changed or that different fragments of data have left or joined the view. These animations are normally not triggered by the user and display automatically when events are fired (such as something coming from a web-socket or notification).
  • Feedback animations: Here lie all animations that indicate causation between different events or give information to the user about an internal process or state of the application. These animations are always the consequence of an action that the user performed, such as clicking on an element, dragging an element to another position or reordering elements.
  • Decorative animations: These animations do not necessarily enhance the flow through the application and normally don’t have a functional meaning. They are purely aesthetic and visually pleasing assets that can give you a competitive advantage over other applications on the same market by differentiating your product from others.

The playground

In order to show the different rapid ways to add animations to your applications, we will be using a fake application named DogApp where you can either foster or adopt different kind of rescued dogs. This is simply a small application that has no commercial relevance and you can use the original code as you see fit.

Animation Methods

React-Native has built-in tools to create animations through the Animated API which is very straightforward and provides low level tools to implement almost any kind of animation. The best looking animations use the native driver instead of being executed through the javascript thread, resulting in a non-blocking experience for the user and in smooth animations.

Even with the Animated API, it takes time to correctly implement transitions in your application as you have to also implement additional code to keep track of your exiting and entering views through variables, which can get messy very quickly. This is specially evident when you use navigation libraries like react-navigation, where you have to keep track of the current screen being rendered and apply optimisations to pre-render transitioning screens.

There are libraries that can help us build different animations efficiently, quickly and with a low amount of effort, which specially important when saving time is an important goal. It comes in handy to have a few tools available to implement animations without sacrificing too much time.

We will now briefly explore each library and the most common use cases where they are used.

React Native Navigation

This library, which is not the same as the react-navigation package that is suggested in React-Native’s documentation, provides navigation for your application through a native implementation (it has the same objective as the react-router library), making all screen changes animated by default and making your applications feel like native products. It has a very straightforward API to implement the interaction flow of your application without you having to worry about smooth screen transitions.

The downside of using this library is that you will mostly forced to use it everywhere, which is not really a bad thing considering that it is equipped with modal views, overlay views and other helpers that can enhance the experience of your users even further, especially in iOS with features like side menus and split views.

For a quick start, let’s say you just created a react-native application using the react-native init <App Name>command and installed the library with the installation guide. Then, the next step is to define the folder structure of your application and the screens that are going to transition. At Nursoft we normally use the following structure:

Project structure

The components folder contains all the reusable components that are shared by all the screens of the application and the screens folder contains all of our screens. Inside this last folder, the index.js will define all the screens available on our application as constants in order to reference them later on.

Defining them as constants is important as it comes in handy when we do navigation operations, like push and pop that allow us to navigate through our app’s navigation stack. These operations are basically transition declarations and move us forward or backwards in the navigation stack. The file index.jsat the screen folder should look like something like this:

screens/index.js

Then, in the App’s index.js file (the application’s entry point), we should define our navigation stack similarly as the following example:

index.js

What we are doing with this library is defining the way our application’s navigation will behave. In this case, it is a stack of screens that will pop on top of each other and appear depending on when a screen is ordered to be put on top of another. You can read more about the definition of this layout here.

In our DogApp example, we have 2 screens that look like this:

After our screens have been correctly registered in, all we have to do is make a push operation in one of the screens to trigger a transition. The code of each screen is the following:

DogList.js
DogProfile.js

The result in iOS looks like this:

This library makes it very easy to have transitions animations on the different screen changes as they come by default on all the screens when the navigation operations are made.

It also comes with the ability to define tab-based layouts, with the caveat that animated screen changes between these tabs is not yet supported or implemented.

Fluid transitions

The previous library is very good when you want your application to have all its screens transitioned without much effort. But sometimes you will want to use react-navigation instead or add transitions that are a little bit more complex in nature.

The most common use case where I choose to ditch the standard react-native-navigation transition is when said transition requires that some of its elements remain on screen during the animation.

For example, after clicking the Adopt button in the Dog’s profile, a designer may define a special transition where the Dog’s image must remain on-screen while the screen transitions. Since images (specially gifs) speak for a thousand words, here’s what we would like to implement in this case:

The transition animation itself is not too complex, but it takes a lot of development time to implement with React-Native’s Animated API and we may want to dedicate more time to other views, our back-end or other more challenging tasks.

This is when Fluid Animations come in place. It works with react-navigation and allows all screen changes to be done with transition animations. One of the best features that it has is the ability to “freeze” elements or allow them to transition while still remaining on the screen.

react-native-navigation and react-navigation are not exactly incompatible with each other. In fact, in order to implement the specific transition triggered by the Adopt button, we can still define a common StackNavigator (which is a container component that enables the navigation capabilities of the library) inside the DogProfile screen and use the React Navigation’s API to trigger navigation changes inside this specific screen.

In this case, we replace the stack navigator with the FluidNavigator instead to allow Fluid Transitions to do its magic. The code in DogProfile should look like this now:

DogProfile.js

With this change, the folder structure changes a little bit and will look like this

For this specific transition, we only care about the details inside DogDetails and AdoptConfirmation, which are the 2 views that you saw earlier. The code for each view is the following:

DogDetails.js
AdoptConfirmation.js

As you can see, aside from the time required to set up our files to use react-navigation, the amount of time required to implement the animation is very low, requiring a few imports and only the need to wrap the content that you want to freeze or persist during the transition inside a Transition element.

Lottie

The previous libraries only considered transition animations, which are very good to communicate intent and when the goal of the user changes. But this is not enough if we want our product to shine and be used by thousands and thousands of people.

Decorative animations are beautiful and carefully crafted animations that give projects that extra finished look and feel. Without them, it is more likely that users will go to an application with an animated mascot or tiny animated details just because they feel and look better.

As programmers and engineers, we are very limited when it comes to implementing complex animations. All we can do is draw many many boxes, shape them and hope that the processor can handle all those box calculations moving across the screen (it gets laggy pretty quick). This is simply too much complexity to something a designer can make more easily, and more beautifully than us.

Lottie is a library that allows designers and animators to create beautiful animations with much more freedom. Any animation software that handles exporting animations in Lottie’s format (which is merely a lightweight JSON file) can be displayed on React-Native applications thanks to this library.

For our example, let’s assume that a designer creates an animation in Adobe After Effects and exports it as a JSON (Following Lottie’s format). The designer then tells us to put it in the middle of a new message screen that shows when an user adopts a dog from the shelter. What we want to achieve is this:

I’m not a designer myself, so I had to borrow an example from Lottie’s website. (Check out Issey’s amazing work!)

Thanks to Lottie, all you have to do is put the animation in your assets folder and display it in a LottieView element, that behaves almost exactly as a regular View. The code for the previous screen is the following:

AdoptConfirmation.js

Lottie can be coordinated with the Animated API and other transition libraries to deliver a unique experience to your users. Anything can be done as it handles the different shapes that compose the animation as vectors (just like SVG does), allowing for your design team’s creativity to flow.

React pose

The only type of animations that we haven’t touched yet are of Supplement and Feedback type. They are also essential in the flow of our projects as they not only will make your feedback interactions more beautiful and satisfactory, but can also help people notice important events, such as the disconnection of a patient’s machinery for a medical application or for when a generic process is completed or interrupted.

In React Native, these animations are tipically accompanied with a change on the state. Feedback animations can run after changing the internal state of typical boolean variables like isPressed, isDragging, isActive, hasMessageArrived and similar ones.

React Pose comes in play for this kind of transitions as it uses the pose abstraction to help us build feedback and supplement animations quick.

Similar to a state, a pose is defined as a specific internal state of an element that can vary overtime. Each pose defines a specific set of properties that the element will have, being scale, position and color the most common cases.

For the DogApp let’s assume that an user wants to foster a dog from the shelter and wants to selec the items on a list that the user wishes to help it with. In this case, we would have a list of features that can be chosen with a switch on them. The switch itself can be made to animate and respond to the user’s interaction with very little code. Here’s what we want to achieve:

For this example, we want to implement the Switch component which will automatically animate when the active prop changes. Here’s the code that makes the animation possible:

Switch.js

As you can see, the amount of code necessary to implement this animation is less than if we wanted to implement it with the Animated API.

By using the pose abstraction and linking it with internal state changes of your components, you can easily make notorious transitions to handle most cases where you want to call the user’s attention or to make sure that all touches have a clear correlation to an interaction.

Conclusions

In this article we quickly reviewed a set of tools that help us build animations in React Native with efficiency in mind. React Native Navigation and Fluid Animations are the best tools to build transitions, while React Pose is the best at doing supplementary and feedback animations. Finally, those tiny differentiating details can be done with decorative animations that Lottie is best suited for.

These tools are great, but are also limited when it comes to very specific or complex animations that you may have to implement in the future. The Animated API is very powerful and can used to achieve those challenges and, if all else fails, you can always handcraft your animations with native code.

Stay tuned for a new post addressing complex animations and ways to implement them with Animated or natively.

The code

We used all these tools in the same application, under the same repository. You can find the DogApp here.

References

--

--