Introduction to React Native Reanimated
Today we are going to see the basics of Reanimated (working from v2) but first of all what is Reanimated and why is it needed? Reanimated is a React Native animation package that allows you to write animations that can run entirely on the UI thread. Of course in React Native, you have the option to build up animations with the React Native Animated APIs and usually, that’s not a huge issue (especially if the animation is a kind of a fire and forget animation).
But when you need to deal with gesture animations it is pretty hard to reach a fluid and nice animation that the final user is expecting.
So let’s get our hands dirty and let’s start to build our simple Reanimated animation.
GitHub - enzomanuelmangano/animate-with-reanimated: Animate with Reanimated is a youtube series…
Animate with Reanimated is a youtube series where I try to build from scratch simple and instructive animations. …
Wait what? Would you prefer a YouTube tutorial? Here it is!
I’ve built up an Expo project with the Expo CLI and I included the Reanimated library.
In this tutorial we’re going to use Reanimated v2.1.0 but of course, every version above v2.0.0 is fine for this tutorial:
To get a more detailed explanation of my setup, feel free to click here!.
So let’s discover together which are the most important ingredients to build up a Reanimated animation.
First ingredient: Shared Values
Keep in mind that a Shared Value can be whatever type of object.
Second ingredient: Reanimated Style
The second most important ingredient is the useAnimatedStyle hook, needed in order to create Reanimated styles. With this hook, we can return a style very similar to the StyleSheet style used by React Native.
If we look closely, we can see that the useAnimatedStyle hook requires two parameters:
- A function that returns a style
- An optional dependency list
In our case, the useAnimatedStyle depends on the progress.value, but we don’t need to specify it in the dependency list since it’s a Shared Value. If the style was dependent on a React state, it would have been necessary to specify the React state in the dependency list.
Third ingredient: Animated View
We’re going to animate something, right? Therefore we need something more powerful than a simple React Native View. The answer to this need is the Animated.View component.
To be honest an Animated.View is simply a React Native View that can also accept Reanimated Styles as input styles.
In order to use an Animated.View, let’s just import Animated from ‘react-native-reanimated’ and let’s use it in the App component.
Of course, we need to style a little bit our Animated.View. Therefore let’s use create a blue square style:
Fourth ingredient: High order functions
Right now we’re not animating our Animated.View. We need of course to pass the Reanimated style. Let’s say we want to animate the opacity from 0 -> 1:
- We need to change the progress initial value
- We must set the “end animation value” inside a useEffect hook.
The final touch? Let’s just wrap the “1” with the withTiming High Order Function:
Feels like magic, right? 🪄
Just to be sure you’re on the right track, here’s all the code we’ve written so far:
The animation seems too fast, isn’t it? Thankfully we can specify additional parameters to the withTiming function. For instance, let’s update the duration:
Do you feel the difference?
Right now we can animate much more than the square’s opacity. Let’s define for example another Shared Value called “scale” with the initial value equal to 1 and let’s add it to the Reanimated Style.
To be able to animate the scale parameter as well, we can also apply the withTiming function:
The timing animation is definitely great but with Reanimated v2 we can push forward this tutorial with a spring animation.
The difference between the two approaches is that:
- withTiming: is based on duration and on a curve
- withSpring: is based on physics (mass, damping, stiffness, etc…)
How to use it? Just replace the withTiming function applied for the scale animation:
For design purposes we can update the opacity animation:
- Animate the opacity from 1 -> 0.5
- Use a spring animation for the opacity as well
Let’s say that we want to change also the border-radius. We aren’t forced to use another Shared Value. We can just reuse the previous progress Shared Value multiplied by some value.
Fifth ingredient: Repetitions
Let’s add another ingredient to our recipe the withRepeat High Order Function. Wouldn’t it be great to repeat the animation?
In order to achieve our goal, let’s just wrap the withSpring animations with the withRepeat function:
Let’s say that we want to repeat it three times and with a “reverse effect” enabled.
Tip: In order to fully understand the power of reverse, feel free to toggle the reverse value and check the differences.
Just for the sake of clarity let’s also rotate the square with an animation. To rotate the object we can use the same technique that we used previously with the borderRadius animation. Therefore let’s multiply the
(progress.value * 2 * Math.PI)rad (of course 2*Math.PI is just a random constant, feel free to use whatever value you want).
That’s almost incredible in my opinion 🤯.
I mean, this animation is quite amazing! We can repeat much more than three times. Let’s say that we want to repeat it infinite times. We can easily do that by replacing the N of repetitions with -1:
Last ingredient: Worklets
The last question is: “when do we need to use worklets?”. I mean… at the beginning of this tutorial we talked about the magical worklet function but till now we didn’t use them. I’m going to answer this question but for now, let’s focus on a specific task.
Let’s say that we need to extract the logic required for the rotate animation. We can easily create a function called handleRotation and we can just return the previous result.
Intuitively at this point, we can simply call handleTranslation in the useAnimatedStyle hook, right?
The issue is that we can’t call a JS function from the UI Thread synchronously. Therefore in order to fix this problem, we just need to mark the handleRotation function as a worklet.
Reload and check out the result 😎
Don’t forget to checkout the GitHub Repo!
Originally published at https://www.reactiive.io on March 31, 2022.