Last month, Software Mansion announced the alpha release of Reanimated 2. Version 2 is a complete paradigm shift in the way we build gestures and animations in React Native.
In Reanimated 1, the strategy employed was to use a declarative domain-specific language to declare gestures and animations beforehand. This approach is powerful, but came with drawbacks:
- learning curve is steep
- some limitations in the available set of instructions
- performance issues at initialization time.
To use the Reanimated v1 Domain Specific Language, you have to adopt a declarative mindset which is challenging, and simple instructions could end-up being quite verbose. Basic mathematical tools such as coordinate conversions, trigonometry, and bezier curves, just to name a few, had to be rewritten using the declarative DSL.
And while the instruction set offered by v1 is large, there are still some use cases where you are forced to cross the React Native async bridge (see Understanding the React Native bridge concept), for example, when doing date or number formatting for instance.
Enter Reanimated 2.
One of the interesting takeaways from the official announcement is that Software Mansion approached the problem from a different angle. Instead of starting from the main constraint, to not cross the React Native bridge, and offering a way to circumvent it, they asked: How would it look if there were no limitations when writing gestures and animations? They started the work on a solution from there.
The code snippet above showcases six properties from worklets. Worklets:
- run on the UI thread.
- are declared via the ‘worklet’ directive.
- can be invoked from the JS thread and receive parameters.
- can invoke other worklet functions synchronously.
- can access constants from the JS thread.
- can asynchronously call functions from the JS thread.
Reanimated 2 liquid-swipe example - click here to see animation
The team at Software Mansion is offering us a couple of great examples to showcase the new Reanimated API. An interesting one is the liquid-swipe example. It features a couple of advanced animation techniques such as bezier curve interpolation, gesture handling, and physics-based animations, showing us that Reanimated 2 is ready for any kind of advanced gestures and animations
When writing gestures and animations, you need to do three things:
- create animation values
- handle gesture states
- assign animation values to component properties.
The new Reanimated API is offering us five new hooks to perform these three tasks.
There are two hooks available to create animation values.
useSharedValue() creates a shared value that are like
useDerivedValue() hook creates a shared value based on some worklet execution. For instance, in the code snippet below, the
theta value is computed in a worklet.
Handle Gesture States
useAnimatedGestureHandler() hook can connect worklets to any gesture handler from react-native-gesture-handler. Each event implements a callback with two parameters: event, which contains the values of the gesture handler, and context which you can conveniently use to keep some state across gesture events
Assign Values to Properties
useAnimatedStyle() returns a style object that can be assigned to an animated component.
useAnimatedProps() is similar to useAnimatedStyle but for animated properties. Now animated props are set via the animatedProps property
A Reanimated 2 Animation Example
Let’s build our first example with Reanimated 2. We have an object that we want to drag around the screen. Like in v1, we create two values for us to translate the card on the x and y axis, and we wrap the card component with a
PanGesture handler. So far so good.
As seen in the above code, the animation values are created using
useSharedValue and assigned to an animated view via
useAnimatedStyle. Now let’s create a gesture handler via
useAnimatedGestureHandler. In our gesture handler, we want to do three things:
- When the gesture starts, we store the
translatevalues into the context object. This allows us to keep track of the cumulated translations across different gestures.
- When the gesture is active, we assign to
translatethe gesture translation plus its offset values.
- When the gesture is released, we want to add a decay animation based on its velocity to give the effect that the view moves like a real physical object
The final example source can be found on GitHub. You can see the gesture in action below.
Reanimated 2 PanGesture example - click here to see the animation
With Reanimated 2, the team at Software Mansion asked: “How would it look if there were no constraints when writing gestures and animations in React Native?” and started from there.
We hope that you are as excited about this new version as we are. Reanimated 2 dramatically lowers the barrier to entry in building complex user-interactions in React Native. It also enables new use-cases where we previously had to cross the React Native bridge (to format values for instance). It also dramatically improves the performance at initialization time which in the future might have a substantial impact on particular tasks such as navigation transitions.
We are looking forward to following the progress of this new exciting way to write gestures and animations.
We're always on the lookout for talent and we’d love to hear from you. Visit our Engineering career page to find out about our open positions.