Creating A Tinder Style Swiping Component With React Native (Part 2 / 2)
Tags: reactnative, animation, gesture, tutorial
Published: 2021-06-27 23:39:03

In my last blog post I described how we can build an app that handles swiping similar to the popular Tinder app. In this post I will show how we can add animations to provide visual feedback to swiping.

To start, we need to import 'Animated' from the react-native library.
```js
import { StyleSheet, Text, View, Image, Animated } from 'react-native';
```

With Animated we can create custom animations using Animated.timing and events using Animated.event. However, before we do that we need to create a variable with Animated.Value that our events and animations will use to effect what our component renders.

In our case, when we swipe we want our View to move to the side in the direction that the user is swiping. So we'll make a variable named translateX that will keep track of the position of the view that we are swiping.
```js
const translateX = new Animated.Value(0)
```

And for our Animated value to be able to affect our view, we need to change our view to be an Animated.View. Animated Views can make use of a transform property in their style prop. The transform property takes a list of single key objects and performs the transformation for each object. 
```js
  <Animated.View style={{backgroundColor:"yellow", width:"75%", height:"75%", transform:[{translateX}]}}>
       <Image source={profile.pic}></Image>
       <Text>{profile.name}</Text>
       <Text>Age: {profile.age}</Text>
       <Text>Likes: {profile.likes.join(', ')}</Text>
  </Animated.View>
```

Now we are ready to start creating events and animations.

For our purposes we only need a single Animation event. This event will be called anytime the users start to swipe and be responsible for updating the translateX variable as the user swipes their finger.

To do this, we'll provide an Animated.Event to the OnGestureEvent for our PanGestureHandler component. Here is the code for our PanGestureHandler component.
```js
<PanGestureHandler
    onHandlerStateChange={handleSwipe}
    onGestureEvent={handlePan}
>
    <Animated.View style={{backgroundColor:"yellow", width:"75%", height:"75%", transform:[{translateX}]}}>
       <Image source={profile.pic}></Image>
       <Text>{profile.name}</Text>
       <Text>Age: {profile.age}</Text>
       <Text>Likes: {profile.likes.join(', ')}</Text>
    </Animated.View>
</PanGestureHandler>
```

And the code for the Animated Event.
```js
const handlePan= Animated.event(
  [{nativeEvent:{translationX:translateX}}],{useNativeDriver:true}
)
```

Now our Animated View will move along with the users finger when they swipe. 

Next, We'll make three animations, swipeLeftAnimation, swipeRightAnimation and reset with Animated.timing. Animated.timing takes two arguments, the value that will be adjusted and an object that describes the animation. The swiping animations will push the view off to the side after the user completes a swipe and reset will bring the view back to the middle. Here is the code for the animations.
```js
const reset = Animated.timing(translateX,{
    toValue:0,
    duration:250,
    useNativeDriver:true
  })

  const swipeRightAnimation = Animated.timing(translateX,{
    toValue: 600,
    duration: 400,
    useNativeDriver:true
  })

  const swipeLeftAnimation = Animated.timing(translateX,{
    toValue: -600,
    duration: 400,
    useNativeDriver:true
  })
```

We'll use the animations in our handleSwipe method which is passed to our onHandlerStateChange prop. Here is the updated handleSwipe method.
```js
const handleSwipe=({nativeEvent}) =>{
    const {state} = nativeEvent
    if(state === 5){
      //handle swipe right
      if(nativeEvent.translationX < -225){
        index++
        swipeRightAnimation.start(()=>{
          //add profile to match list
          setProfile(profiles[index%3])
        })
      }
      //handle swipe left
      else if(nativeEvent.translationX > 225){
        index++
        swipeLeftAnimation.start(()=>{
          setProfile(profiles[index%3])
        })
      }
      //handle uncompleted swipe
      else reset.start()
    }
  }
```
Now after a completed swipe the view will be pushed off the screen and appear back in the middle. After an uncompleted swipe the view will be gracefully repositioned back to the middle.