Cole Redfearn Fullstack engineer, golfer, and explorer. Always curious!

Deep dive into React Native Reanimated

5 min read 1448

React Native Reanimated

React Native Reanimated is a powerful, intuitive library that allows you to create smooth animations and interactions for iOS and Android applications. Although there are many versatile and performant animation libraries for React Native, including the built-in Animated API, we’ll examine Reanimated in-depth to discover why it’s the superior choice in my opinion.

Let’s get started!

Reanimated code execution

Reanimated’s core strength lies in its ability to improve the performance and responsiveness of React Native applications, giving animations a smooth finish that can be achieved only through instantaneous code execution.

To understand how Reanimated works, we first need to understand how React Native executes code.

React Native threads

React Native has three separate threads that allow the execution of time-intensive JavaScript code without affecting the UI’s responsiveness. The UI thread is the native thread. It runs either Swift or Objective C for iOS and either Java or Kotlin for Android. The application’s UI is manipulated solely on the UI thread.

The JavaScript thread is responsible for the render logic, like which views are displayed and in what manner. It executes JavaScript separately via a JavaScript engine. Finally, the bridge enables asynchronous communication between the UI and the JavaScript thread. To avoid slowing down performance, it should only be used to transfer small amounts of data.

These interactions start on the JavaScript thread and must be reflected on the main thread, potentially causing problems when dealing with event-driven interactions.

Reanimated vs. the Animated API

Because communication between the UI and the JavaScript thread is asynchronous, the Animated API delays updates by at least one frame, which lasts approximately 16.67ms. The delay can last even longer when the JavaScript thread is also executing other processes like running React diffing and processing network requests.

Known as dropping a frame, these delays can harm your UX and make animations appear clunky. Reanimated solves this problem by removing animation and event handling logic from the JavaScript thread and running it directly on the UI thread.

Additionally, Reanimated defines worklets, which are tiny chunks of JavaScript code that can be moved to a separate JavaScript virtual machine and executed synchronously on the UI thread. Worklets cause animations to run as soon as they are triggered, creating a more satisfying UX.

Shared Values

Shared Values, which are similar to stateful data in a regular React application, store dynamic data that you can animate in Reanimated. However, instead of sharing data between components like you would with stateful data, Shared Values share data between the UI thread and the JavaScript thread.

When data inside of these Share Values is updated, the Reanimated library registers the change and executes an animation, similar to how React re-renders a component when state is updated.

Creating a Shared Value looks quite similar to creating a piece of state with the useState Hook; simply use the useSharedValue Hook instead.

Let’s say we want to create a box that changes height when a button is pressed. We’ll define a boxHeight variable as a Shared Value so that we can share it between the UI thread and the JavaScript thread during the animation:

const boxHeight = useSharedValue(150);

In the example above, we created a Shared Value called boxHeight and set its initial value to 150. To access the boxHeight value later in your code, you must reference boxHeight.value instead of just boxHeight.

The useSharedValue Hook returns an object, and the initial value is saved to the .value property of the object. To update the Shared Value, which is typically done after some predetermined user input, simply update the .value property within a function. Reanimated will register the change:

function toggleHeight() {
  boxHeight.value === 450 ?
  boxHeight.value = 150 :
  boxHeight.value = 450;

Now, let’s explore how we can use these Shared Values in Reanimated’s worklets.

Reanimated worklets

Worklets are simple functions that allow us to execute JavaScript code synchronously on the UI thread. Typically, worklets return a React component’s style property. A worklet is triggered by any change to the Shared Value it references.

To declare a worklet, we can use the worklet directive in the beginning of the function definition. In the code block below, we are declaring the boxAnimation function using the worklet directive, indicating that the function is a worklet. We are returning an updated height property using the Shared Value boxHeight:

const boxAnimation = () => {
  return {
    height: withTiming(boxHeight.value, {duration: 750})

More commonly, we can use the useAnimatedStyle Hook to declare a worklet, which allows us to pass in a callback function as an argument. Now, the callback function will be treated as a worklet:

const boxAnimation = useAnimatedStyle(() => {
  return {
    height: withTiming(boxHeight.value, {duration: 750})

Of the two methods for declaring a worklet, I recommend using the useAnimatedStyle Hook. To use the worklet directive method, we must add a secondary function that calls the runOnUI method and passes the boxAnimation function as a parameter. On the other hand, the useAnimatedStyle hook abstracts that secondary function away, automatically running the callback passed to the useAnimatedStyle Hook on the UI thread.

In both of our examples, whenever the value of boxHeight.value is updated, the worklet will trigger an animation showing the box either expanding or contracting vertically.

Utility methods


In our examples above, we used the withTiming utility method, which allows us to create a simple animation that gradually transitions from its start point to its endpoint, giving us the ability to control the duration and acceleration of the transition. 

More great articles from LogRocket:

withTiming takes two parameters. The first, which is required, is the Shared Value that will update. In our case, it is boxHeight.

The second optional parameter is an object with two properties. duration controls the length of time the animation takes, and easing controls the animation’s acceleration and deceleration. The default values are 300ms for duration and in-out quad easing for easing.


The withSpring method is similar to withTiming, however, it creates a different animation effect in which the element passes its endpoint before settling into its ending position.

withSpring only has one required parameter, which is the Shared Value to be updated. It also has six optional parameters listed below. However, the default values will suffice for most use cases:

  • damping: 10
  • mass: 1
  • stiffness: 100
  • overshootClamping: false
  • restDisplacementThreshold: 0.01
  • restSpeedThreshold: 2

useAnimatedStyle Hook

In our previous example, the useAnimatedStyle Hook creates a worklet that links the Shared Value boxHeight with a component that uses boxHeight.value in its style properties. When giving React components properties, we must use the component version that we can animate.

For example, instead of using a <View /> tag, we should use an <Animated.View /> tag. All children of <Animated.View /> will be subject to the animation applied to the parent.

When setting styles for the component, be sure to pass the styles as an array. The first element is an object containing all of the styles you would typically use, including height. The second element is the worklet that was defined earlier.

Now, let’s combine all of the Reanimated tools that we’ve covered to create a simple grey box that expands and contracts when we press a button:

// import statements where we add the functionality to use hooks and methods from Reanimated
import React from 'react';
import { View, Button } from 'react-native';
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
export default function ExpandingTextBox() {
  // creating shared value via useSharedValue
  const boxHeight = useSharedValue(150);
  // creating worklet via useAnimatedStyle, and incorporating the withTiming method
  const boxAnimation = useAnimatedStyle(() => {
    return {
      height: withTiming(boxHeight.value, {duration: 750})
  // function that toggles the value of boxHeight so it can expand and contract
  function toggleHeight() {
    boxHeight.value === 450 ?
    boxHeight.value = 150 :
    boxHeight.value = 450;
  // styles to use on our grey box
  const styles = {
    box: {
      width: 400,
      height: 150,
      backgroundColor: 'grey',
      borderRadius: 15,
      margin: 100,
      padding: 20,
      display: 'flex'
  return (
    <View style={}>
      {/* Animated.View component, with the typical styles contained in,
and the worklet "boxHeight" that updates the height property alongside it */}
      <Animated.View style={[, boxAnimation]}>
        {/* button that fires off toggleHeight() function every time it's pressed */}
        <Button title='More' onPress={() => toggleHeight()} />

The output of the code above will look like the animation below:

Reanimated Gif Dropdown

Let’s add another Shared Value and worklet to control text opacity. We’ll also add some more detail to the styling.

Now, we have a fully functional animated text dropdown!

Reanimated Gif Styling


Reanimated offloads event-driven interactions from the JavaScript thread and instead executes them synchronously on the UI thread. With Reanimated, you no longer have to worry about dropping frames or limiting the workload of your JavaScript thread.

For more information on Reanimated’s methods, hooks, and animations, I recommend checking out the Reanimated documentation.

LogRocket: Instantly recreate issues in your React Native apps.

LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your React Native apps — .

Cole Redfearn Fullstack engineer, golfer, and explorer. Always curious!

One Reply to “Deep dive into React Native Reanimated”

Leave a Reply