How to use Reanimated 2 (a beginners guide)
Tags: reactnative, reanimated, reanimated2
Published: 2021-05-12 12:25:13

---
title: How to use Reanimated 2 (a beginners guide)
published: true
description: In this guide we'll learn what the core building blocks of Reanimated 2 are and how ot use them.
tags: reactnative, reanimated, reanimated2
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ybrjebpd5gf9zq4hl59b.jpg
canonical_url: https://www.reactnativeschool.com/how-to-use-reanimated-2-a-beginners-guide)
---


Reanimated 2 is a hyper powerful library that [all the](https://twitter.com/wcandillon) [cool](https://twitter.com/mironcatalin) [kids](https://twitter.com/reactnavigation) use but has always been a bit of a blackbox to me... I saw the power of it but was overwhelmed by the API.

> This post was [originally published on React Native School](https://www.reactnativeschool.com/how-to-use-reanimated-2-a-beginners-guide). If you’re interested in hundreds of React Native tutorials and courses be sure to check it out!

Today I want to share with you what I've learned and we'll create our first Reanimated 2 animation together - an image that changes sizes.

Let's start with an app that renders a 100x100 image. All standard React Native.

```jsx
import React from 'react';
import { View, TouchableOpacity, Image } from 'react-native';

export default () => {
  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column',
        backgroundColor: '#7CA1B4',
      }}
    >
      <TouchableOpacity
        onPress={() => {
          alert('todo!');
        }}
      >
        <Image
          source={require('./rns.png')}
          resizeMode="contain"
          style={{ width: 100, height: 100 }}
        />
      </TouchableOpacity>
    </View>
  );
};
```

![01](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvf9u1feb0ewwsy7k2sk.png)
 

We'll be animating the size of the image. That means that we need to store the value to be animated somewhere.

Reanimated 2 has a concept of [shared values](https://docs.swmansion.com/react-native-reanimated/docs/shared-values). These are values that can be shared across different threads (think JavaScript thread and UI thread) thus the name of shared value.

It's where you'll want to store your "animateable" data - in this case the random number that we'll use to drive the size of the image.

`useSharedValue` returns a value - similar to using `.current` on a `useRef` hook - that means that we can't just access the result directly. We need to access the `.value` property of the returned data.

Also note in the following code that I've replaced the `Image` component with an `Animated.Image`. This is in preparation for when the `randomNumber` value will change.

```jsx
import React from 'react';
import { View, TouchableOpacity, Image } from 'react-native';
import Animated, { useSharedValue } from 'react-native-reanimated';

export default () => {
  const randomNumber = useSharedValue(100);

  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column',
        backgroundColor: '#7CA1B4',
      }}
    >
      <TouchableOpacity
        onPress={() => {
          alert('todo!');
        }}
      >
        <Animated.Image
          source={require('./rns.png')}
          resizeMode="contain"
          style={{ width: randomNumber.value, height: randomNumber.value }}
        />
      </TouchableOpacity>
    </View>
  );
};
```

Now let's go ahead and change that `randomNumber`. Make sure you use `.value` when accessingly the data.

```jsx
import React from 'react';
import { View, TouchableOpacity, Image } from 'react-native';
import Animated, { useSharedValue } from 'react-native-reanimated';

export default () => {
  const randomNumber = useSharedValue(100);

  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column',
        backgroundColor: '#7CA1B4',
      }}
    >
      <TouchableOpacity
        onPress={() => {
          randomNumber.value = Math.random() * 350;
        }}
      >
        <Animated.Image
          source={require('./rns.png')}
          resizeMode="contain"
          style={{ width: randomNumber.value, height: randomNumber.value }}
        />
      </TouchableOpacity>
    </View>
  );
};
```

But when we press the image nothing is happening... why?

It's not changing because, unlike when calling `setState`, it doesn't cause a re-render to happen (which is good) we're just changing a value.

What we need to do is [spawn a worklet](https://docs.swmansion.com/react-native-reanimated/docs/worklets) that can adjust to changes in `randomNumber`.

This worklet will run on the UI thread (rather than the JavaScript thread) allowing us to see a smooth native animation.

To spawn this worklet we're going to use the [`useAnimatedStyle` hook](https://docs.swmansion.com/react-native-reanimated/docs/api/useAnimatedStyle). This hook will return a style object that updates with `randomNumber`. This style object can then be applied to our `Animated.Image`.

`useAnimateStyle` is similar to `useEffect` but actually returns a value (the style object).

```jsx
import React from 'react';
import { View, TouchableOpacity, Image } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
} from 'react-native-reanimated';

export default () => {
  const randomNumber = useSharedValue(100);

  const style = useAnimatedStyle(() => {
    return { width: randomNumber.value, height: randomNumber.value };
  });

  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column',
        backgroundColor: '#7CA1B4',
      }}
    >
      <TouchableOpacity
        onPress={() => {
          randomNumber.value = Math.random() * 350;
        }}
      >
        <Animated.Image
          source={require('./rns.png')}
          resizeMode="contain"
          style={style}
        />
      </TouchableOpacity>
    </View>
  );
};
```

Now when we press the image the size of it changes (granted it's not animated - we'll get to that).

![https://media.giphy.com/media/GjKW16FwHfXOtkadLy/giphy.gif](https://media.giphy.com/media/GjKW16FwHfXOtkadLy/giphy.gif)

The final piece of (this) puzzle is to actually animate the values. We've created all the necessary relationships between data and have things updating where they need to be - now we need to [choose the animation](https://docs.swmansion.com/react-native-reanimated/docs/animations) to use.

Today we'll make "springy".

By importing `withSpring` we can tell Reanimated 2 how we want that data to change.

```jsx
import React from 'react';
import { View, TouchableOpacity, Image } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

export default () => {
  const randomNumber = useSharedValue(100);

  const style = useAnimatedStyle(() => {
    return {
      width: randomNumber.value,
      height: randomNumber.value,
    };
  });

  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column',
        backgroundColor: '#7CA1B4',
      }}
    >
      <TouchableOpacity
        onPress={() => {
          randomNumber.value = withSpring(Math.random() * 350);
        }}
      >
        <Animated.Image
          source={require('./rns.png')}
          resizeMode="contain"
          style={style}
        />
      </TouchableOpacity>
    </View>
  );
};
```

![https://media.giphy.com/media/RSukX8m2ogtoKF0NWO/giphy.gif](https://media.giphy.com/media/RSukX8m2ogtoKF0NWO/giphy.gif)

Alternatively we could use `withSpring` inside of `useAnimatedStyle` to customize how each property changes.

```jsx
import React from 'react';
import { View, TouchableOpacity, Image } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

export default () => {
  const randomNumber = useSharedValue(100);

  const style = useAnimatedStyle(() => {
    return {
      width: withSpring(randomNumber.value),
      height: withSpring(randomNumber.value, { stiffness: 10 }),
    };
  });

  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column',
        backgroundColor: '#7CA1B4',
      }}
    >
      <TouchableOpacity
        onPress={() => {
          randomNumber.value = Math.random() * 350;
        }}
      >
        <Animated.Image
          source={require('./rns.png')}
          resizeMode="contain"
          style={style}
        />
      </TouchableOpacity>
    </View>
  );
};
```

![https://media.giphy.com/media/9cJXjCvcDq41WKRvKz/giphy.gif](https://media.giphy.com/media/9cJXjCvcDq41WKRvKz/giphy.gif)

And that's on me trying to figure out the moving parts of Reanimated 2. To me it's a pretty complex library to first learn but the power of it is incredible.

If you have any comments/corrections/questions please [reach out on Twitter](https://twitter.com/learn_rn).