React Native comes with an awesome Animated API to create smooth and performant animations in your app. It is included with react native which means no dependencies or installations with great cross platform support!

It’s already amazing.

I will be using some simple functions from the Animated API to get you started, after which reading the official documentation here will make much more sense.

  1. Animated.Value
    • Holds an animation state.
    • It is always a javascript Number
    • Animations react to changes in this value
  1. Animated.View
    • A component that can be animated
    • This view reacts to changes in an Animated.Value
    • Behaves exactly like a normal <View /> but with superpowers
  1. Animated.timing
    • tweens an animated value to a final value
    • takes in config like duration, easing, etc.
  1. useRef
    • it returns a mutable object whose value will not change across re-renders.
    • it holds its value in the .current property

Setup

  1. create a ref object using useRef
  2. put an animated value with some initial value in the ref object
  3. pick a view you want to animate, and wrap it in an Animated.View
import React, { useRef } from "react";
import { View, Animated } from "react-native";

const App = () => {
  const anim = useRef(new Animated.Value(1));
  return (
    <View style={{ flex: 1 }}>
      <Animated.View>
       {/* Any component that needs to be animated */}
      </Animated.View>
    </View>
  );
};

export default app;

The Heartbeat

A heartbeat animation like this has 3 main steps

  1. increase size
  2. go back to original size
  3. loop back to step 1

Translating this to react native looks something like this -

Modifying size

To increase the size based on a factor, react native has a transform property called “scale” in View styles. A scale value of 2 means the element will be enlarged to twice it’s size.

eg. <View style={{transform: [scale: 2]}}> {...} </View>

Running animations in sequence

The heart beat animation needs to first increase size, then decrease it. Animated.timing is used to do the individual animation. Animated.sequence takes an array of animations and runs them one after the other.

eg. Animated.sequence([Animated.timing(...), Animated.timing(...),])

Making an animation loop

To make our scale animation loop indefinitely, we must use Animated.loop. It takes an animation and loops it infinitely(by default) or for a set number of times if specified

eg. Animated.loop(Animated.timing(...))

Final config

// makes the sequence loop
Animated.loop(
  // runs given animations in a sequence
  Animated.sequence([
    // increase size
    Animated.timing(anim.current, {
      toValue: 1.2,
      duration: 200,
    }),
    // decrease size
    Animated.timing(anim.current, {
      toValue: 1,
      duration: 200,
    }),
  ])
).start();

The Shake

A shake animation is usually used to denote an error state. MacOS uses this in a lot of places when the user does something wrong like an incorrect password. A shake animation is very similar to the heartbeat animation above. You can try to breakdown the animation into smaller steps yourself before proceeding.

4 main steps -

  1. move element to the left a tiny bit
  2. move element to the right a tiny bit
  3. move element back the the original position
  4. loop 2 times (increase this number for a longer duration)

moving an element horizontally

To move an element horizontally, react native has a transform property called “translateX” in View styles. A translateX value of 2 means the element will be moved to the right by 2 units and -ve values move it to the left.

eg. <View style={{transform: [translateX: 2]}}> {...} </View>

Final config

// makes the sequence loop
Animated.loop(
  // runs the animation array in sequence
  Animated.sequence([
    // shift element to the left by 2 units
    Animated.timing(anim.current, {
      toValue: -2,
      duration: 50,
    }),
    // shift element to the right by 2 units
    Animated.timing(anim.current, {
      toValue: 2,
      duration: 50,
    }),
    // bring the element back to its original position
    Animated.timing(anim.current, {
      toValue: 0,
      duration: 50,
    }),
  ]),
  // loops the above animation config 2 times
  { iterations: 2 }
).start();

The documentation will be easier to follow if you are comfortable with smaller animations and the basic Animated APIs.

The key is to breakdown your animations into smaller steps and thinking of them in terms of being small Animated.timing components interacting with each other. Intermediate animated APIs like interpolate, easing, gestures, etc provide a lot of control over animations in react native.

Reach out if you’d like more of such content! :)