Different ways to implement a circular / infinite animation in react-native

October 26, 2019

I needed a simple loading animation for a project I’m currently working on. Nothing spectacular, basically just rotating an image an infinite amount of times.

This is the end goal that I wanted to achieve.

Animating with react-native’s Animated API is quite simple.

From playing around, I found that there’s really two ways of making an infinite animation in react-native.

Recursive function method

The first method, which offers a bit more control, but, in my opinion, isn’t as clean. Is to just recursively call on an animation function.

In essence, create a function that’ll perform the animation once. When that iteration completes, the animation function will call upon itself. Iterating an infinite amount of times (You could implement a counter if you want iteration control).

    [....]
    const iconAnimation = new Animated.Value(0);

    // Setup the animation  function
    const animateIcon = () => {
        Animated.sequence([
            Animated.delay(100),
            Animated.timing(
                iconAnimation,
                {
                    toValue: 1,
                    duration: 800,
                    useNativeDriver: true
                }
            ),
            Animated.timing(
                iconAnimation,
                {
                    toValue: 0,
                    duration: 0,
                    useNativeDriver: true
                }
            ),
        // Call on self when animation completes
        ]).start(animateIcon)
    };

    // Call on the animation when component is mounted
    useEffect(() => {
        animateIcon();
    }, []);
    [...]

The downside of this approach, as earlier mentioned, is because that the code isn’t very clear. You’ll read through all of the code, then find that the function/animation is fired inside of a useEffect (or a componentDidMount).

So you’ll have to go back to the actual animation-funcation to, again, read through it.

Animated.loop method

The other way is using the Animated.loop method. It doesn’t give you fine-tuning control. I.e. there’s no callback when an iteration is done, only when all iterations have completed. Which isn’t going to happen if you have an infinite amount of iterations).

The biggest pro with Animated.loop is that from a glance you know exactly what it does. The code is a lot more semantically clear. No going back and forth inside of the component. It does what it says on the can.

    [...]
    const iconAnimation = new Animated.Value(0);

    // Loop the animation
    Animated.loop(
        Animated.sequence([
            Animated.delay(100),
            Animated.timing(
                iconAnimation,
                {
                    toValue: 1,
                    duration: 800,
                    useNativeDriver: true
                }
            ),
            Animated.timing(
                iconAnimation,
                {
                    toValue: 0,
                    duration: 0,
                    useNativeDriver: true
                }
            ),
        ]),
        {}
    ).start();
    [...]

Conclusion

In this project, since I don’t need any fine control. I really just want the animation to repeat itself over and over, I decided to go with the secondary approach. Because I find it a lot more readable and it’s easier to understand what the goal is.

Here’s the complete functional component if you want to implement something similar yourself.

Tags