Beginners Guide to React Native Animation

Introduction

React Native makes building a simple cross-platform app fun, especially if you know JavaScript. A lot can be built with components like <View> and <Text>. But they can only get you so far.

Mobile apps need some sort of animation. Unless you’re used to making animations, the jump in complexity can be daunting.

This Beginners Guide to React Native Animation aims to help you get over that initial hurdle.

Animation Basics

Before starting the basics of animation in React Native. It’s worth explaining the basics of animation itself.

Animation is the process of making the illusion of motion and the illusion of change by means of the rapid display of a sequence of images that minimally differ from each other.

Or in other words, repeatedly drawing something slightly differently, makes things look animated.
Unfortunately, we can’t load our apps with 1000s of slightly different images. That would lead to all manner of problems with size, how you interact with it etc.

So, we need our own illusions.

Illusions, aka Maths!

Don’t worry, you don’t need to be a math genius to understand this.

Let’s take the simple example of moving a red box from the top of the screen to the bottom.

render(){
	<View style={{styles.redboxTop}} />
}
…
…
const styles = StyleSheet.create({
	redboxTop: {
		position: "absolute",
		left: width / 2 - 15,
		top: 10,
		height: 30,
		width: 30,
		backgroundColor: "red"
	}
});

To draw the box at the bottom of the screen, you write some code like:

render(){
	<View style={{styles.redboxBottom}} />
}
…
…
const styles = StyleSheet.create({
	redboxBottom: {
		position: "absolute",
		left: width / 2 - 15,
		top: height - 30,
		height: 30,
		width: 30,
		backgroundColor: "red"
	}
});

The only difference here is the value assigned to the top style. It’s changed from 0 to X.

So you could animate the box by creating a loop from 0 to X and redrawing the box with the loop variable every time. As we know, in React, you get a redraw every time you call setState. So let’s redraw the box, with the top value based on state every 10ms.

constructor(props) {
	super(props);
	this.state = { top: 0 };
	this._interval = 0;
}

componentWillMount() {
	this._interval = setInterval(() => {
		if (this.state.top >= height - 30) {
			clearInterval(this._interval);
		}
		this.setState((prevState, props) => {
			return { top: prevState.top + 1 };
		});
	}, 10);
}

render() {
	return <View style={[styles.redboxAnim, { top: this.state.top }]} />;
}

const styles = StyleSheet.create({
	redboxAnim: {
		position: "absolute",
		left: width / 2 - 15,
		top: 10,
		height: 30,
		width: 30,
		backgroundColor: "red"
	}
});
React Native - For Loop Animation

React Native – For Loop Animation

It works! I’ve included the value of top so you can see it change and how the changes relate to the position of the cube.

That’s the basics of animation. Tie a variable that we control, to a style property and changed it over time.

Problem – A lot of code

That’s quite a lot of effort and code for something as simple as moving a box. Try and imagine the code you would need to do something more complex. This approach isn’t going to scale to anything much more complex.

This is where React Native Animated comes in.

Solution – React Native Animated API

The [Animated API] provides components and helpers to make our lives easier. The components are the same as the non-Animated components. But without all the JavaScript ~diffing, reconciliation~ magic.

We can also use the React Animated helpers, like Animated.Value and Animated.timing. These help with the calculations and update the native components for us.

First, instead of declaring a variable for our for loop, use Animated.Value. This is what we will tie to our style property. But instead of our code updating the value, we will let React Native Animated do it.

How does React Native Animated update values? Again, there are several helpers, but for now, we’ll keep things simple and use Animated.timing. For example, this

this.top = new Animated.Value(0);

Animated.timing(this.top, {
	toValue: height - 30,
	duration: 1500
}).start();

Which takes the value stored in this._top and updates over the course of 1500 ms to the value in `toValue’. React Native takes care of figuring out by how much top needs to change each update. So we end up with a lot less code.

All we need to do is tie that to our top CSS variable, so the complete listing of the component is:

import React, { Component } from "react";
import {
	Animated,
	AppRegistry,
	Dimensions,
	StyleSheet,
	Text,
	View
} from "react-native";

let { width, height } = Dimensions.get("window");

export default class AnimatedSquare extends Component {
	constructor(props) {
		super(props);
		this.top = new Animated.Value(0);
	}
	
	componentWillMount() {
		Animated.timing(this.top, {
			toValue: height - 30,
			duration: 1500
		}).start();
	}
	
	render() {
		return (
			<Animated.View
				style={[
					styles.redboxAnim,
					{
						top: this.top
					}
				]}
			/>
		);
	}
}

const styles = StyleSheet.create({
	redboxAnim: {
		position: "absolute",
		left: width / 2 - 15,
		top: 10,
		height: 30,
		width: 30,
		backgroundColor: "red"
	}
});
React Native - Animated Timing - Animation

React Native – Animated Timing – Animation

Again, I’ve included the value of top so you can see it change over time.

Conclusion

We’ve seen that animation is an “illusion”. It boils down to drawing slightly different images in rapid succession.

To achieve that effect in React Native (or the web for that matter), we can tie variables to style properties. Then change those variables over time, redrawing the screen as we go.

Tie a variable that we control, to a style property and changed it over time.

You’re more than welcome to do that the hard way, but React Native has some nice helpers to make it easier. In this post I used Animated.timing, but there are others.

Remember though, it boils down to changing a number over time. Then using that number to update the value of a style property.

Please let me know if I’ve made a mistake in this post. Or you think I’m missing a trick in my explanation. React Native Animated didn’t click for me till I made this realization. I hope this helps you too.

4 Responses to “Beginners Guide to React Native Animation”

  1. Hey Matt, nice post! Animation is one of those things a beginner can find complicated to start with.

  2. Yamil Díaz Aguirre says:

    It’s working fine, but I have a problem when I execute this.setState while I’m using Animated.timing because it’s re-render my screen and my animations are restarted.

    Can you help me?

    Thank you very much!

    • Where have you put the start() to Animated.timing? Sounds like it *might* be in something that is called each render. Could you share the code somewhere? Or perhaps link to a stackoverflow question.

Leave a Reply

Your email address will not be published. Required fields are marked *