React Native Reanimated
Declarative Animation in React-Native
Updated: 03 September 2023
References:
- the Reanimated docs
- the Release Intro Blog Post
- this Intro to React Native Reanimated 2
- this Webinar on React Native Reanimated 2
Initialize an App
To create a new app, do the following using the Expo CLI (I’ve covered the basics for this here)
And then select the option for Blank (Typescript)
Install Reanimated
Optionally, to add support for Web update your babel.config.js
file add the reanimated
plugin: react-native-reanimated/plugin
, so your file should now look like this:
Updating Views
Usually when creating components you can mix static and dynamic styles, this allows us to mix styles from our StyleSheet
with styles from a useAnimatedStyle
hook, so something like this:
Managing Animated State
Shared Values are values that can be read from both the JS and UI Threads and help to:
- Carry data
- Drive Animations
- Provide Relativeness
Can be created using the useSharedValue
hook, similar to Animated.value
but can carry any type of data that we want
These values can also be directly assigned to in order to update them
Another hook we can use to calculate a value based on the value of sharedValue
is the useDerivedValue
hook, which can be used in association with the above example like so:
Animation
Whe working with animations there’s a concept of an animation assigner, this is basically a function that creates an animated value that can then be assigned to a shared value. Some functions available for this are:
Easing
functions likeEasing.bezier
orEasing.bounce
withTiming
to set an animation to happen over a set amount of timewithSpring
to make an animation springy
These can be used like so:
Additionally there are modifiers that can be used with an animation, something like delay
:
Gestures
Gesture handling in React Native is usually done using the react-native-gesture-handler
library. At the top-level the library exposes gestureHandlerRootHOC
and GestureHandlerRootView
. Before your application will be able to register gestures you have to wrap your application with either the HOC
or RootView
mentioned above
This would be done at the top-level of your app like so
Using the gestureHandlerRootHOC
:
App.tsx
Or using GestureHandlerRootView
:
App.tsx
When handling gestures we have a useAnimatedGestureHandler
which can take an object of method handlers, for example setting an onActive
handler like below
We can also add an animation to the value we calculate, so something like withSpring
Worklets
In React-Native we have a few main threads in which code is executed:
- The Main JS thread where our JavaScript code is executed
- The UI Thread in which rendering Native views are done
- The Native Modules thread where Native Code is run
Reanimated adds to this by running some additional JS code in the UI Thread instead of the main JS thread, these are called worklets, and they’re pretty much just functions
A Worklet can be defined using either the worklet
directive or is implied for a lambda used in the useAnimatedStyle
hook
A simple worklet can look like so:
Or, in the useAnimatedStyle
hook:
useSharedValue
creates a value that can be accessed from the UI ThreaduseAnimatedStyle
uses a worklet which can returns a stylewithSpring
creates an interpolated value
Using the above, we can render an element with a variable width
using the Animated.View
Note that though worklets can call non-worklet methods, those methods will be executed on the JS Thread and not the UI Thread